Category Archives: 随笔

新浪容器云入门教程(1)-如何部署一个go web应用

新浪容器云介绍

如果您熟知云计算,也知道云计算有几个分类,那么PaaS你也一定不陌生。但是在docker这种技术出来之前主要还是依赖进程之间的隔离来完成PaaS平台的设计的。举一个通俗的例子,如果我想实现两个网站的隔离,传统的做法肯定是不同的用户启动一个httpd进程来隔离。但是这么整还是得借助cgroup去限制各个进程的cpu使用、内存使用等等,不能让一个用户就把一个服务器的CPU、内存耗尽了。但是SAE的实现是基于请求之间的隔离实现。但是这种方式的好处是统一调度、我们对各种软件的修改例如操作系统的优化、httpd的调优、php的改进等等都能被所用的用户“快速的享受到”我们改进的好处。但是凡事有利就有弊,害处就是牺牲了很多的用户体验,例如:

  • 本地不能写了,直接导致的恶果是诸如discuz等传统的软件没法直接安装了
  • 好多的php函数、Apache的配置文件没法写了
  • 只能使用平台提供的软件版本,例如php的版本、jdk的版本、Python的版本等等

总结起来一句话,大家觉得在享受到极快的部署体验下(可能注册个应用立马就能访问了),还是丧失了一些灵活性。当然这也成为好多用户吐槽的原因。其实各家做相同模式业务的也都知道有这个问题,都会面临用户通过各种渠道质问为啥这个在我本地跑的好好地到你们那就不能用的问题。也是在这种大背景下,我们几经波折的推出了“容器云平台”。那么容器云到底是个什么东西呢?

啥是容器云

其实容器云,顾名思义就是能运行很多很多容器的云平台。而容器既不是大家熟知的jetty容器也不是也不是大家用来装双氧水的容器,就是docker容器。也有很多人将它称为轻量级虚拟机,我觉得这个称谓也是比较合理的,我们不妨叫他“昙花一现的虚拟机”,为什么这么说呢,因为docker这个东西没有“重启”,“关闭”这一说,当你关闭一个启动的docker容器或者重启时,其实是docker daemon又把相同的镜像又启动了一个新的。(以上概念在新浪云容器如此,其他家可能有一些技术能保证上次写的文件还在等等可能不一致。)所以说到这里大家应该知道容器云是个什么东西了,其实就是帮你管理启动好多“一次性虚拟机”的云平台。所以为了达成以上几点,又衍生出了一个概念那就是“镜像”。

什么是镜像

其实好多东西都叫镜像,不论是虚拟机的快照,还是大家安装各种虚拟机时下载的ISO文件等等,都被称为“镜像”,docker的镜像也叫镜像,可以狭隘的理解为docker容器的系统快照,只是这个快照不包含系统运行时产生的文件。

在新浪云容器创建几个容器

讲了以上这么多概念终于能切入到本文介绍的正文了,那就是如何在新浪云容器(以下为了方便,简称为我们自己给自己定的缩写SC2了,应该是Sina Cloud Containers的缩写,为了防止和上海某著名跑车协会撞名,就叫SC2了)。登录http://sc2.sinacloud.com,选择“应用”tab就能看到“创建应用”了。大致可以看到类似以下的界面(我们还在频繁的开发修改中,后来的读者看到的界面可能不一致):

先开始创建一个实例就可以了。这时候就创建好了一个容器,但是为了给大家省钱,默认是不会启动任何容器的。因为容器的计费方式和SAE平台的并不一致,是按容器的启动时间和你选的配置的计价单位计算扣除费用的。

上传我们的代码

为了方便大家先体验,我们在github给大家准备好了入门的示例代码,看这里:https://github.com/sinacloud/go-getting-started。我们将代码先下载到本地来,然后用git上传到我们的应用中,注意:我们的git不知道用户上传证书,所以需要大家自动输入安全邮箱和密码才能提交,但是从我的实际测试中看,需要git 客户端的版本在1.8以上才能弹出来让人输入邮箱和密码,如果你是从centos6默认的yum仓库安装的git,那么你的git版本是有问题的。我们可以执行

[root@vm237147/tmp/f2p2xu8381/src/cow-master]#git version
git version 1.8.3.1

看到当前环境的git版本,当然windows下也是有git的,推荐使用这个:http://pan.baidu.com/s/1geaPw4r

准备好git客户端后,我们需要做一个“选择”了,到底是通过git提交的时候自动就把代码构建为docker的镜像呢,这种比较适合我会在本地一次修改,测试通过后再提交,还有我们也提供异步的镜像构建。意思就是说你可以把git只当一个代码管理的工具使用,从sc2的在线管理平台处就能设定。在这个地方的“勾”:

以下是我通过自动部署时候的命令行样子:

如果git只是提交代码,我们需要去到sc2的在线管理平台部署我们的应用,其实过程都是一样的,只是触发的地方不一样,如果是在界面上完成的,大概是长这个样子的(当然我这部署失败了大家不要在意):

部署后的样子

这时候我们就能看到启动好的容器了,从sc2的管理面板上就能看到容器使用的CPU、内存等,还能看到各种日志。容器的实时状态:

访问日志、错误日志、运维日志的样子:

Godep是啥

写go的都知道我们我们在代码里面会这么写

import "github.com/xx/xx"

其实go在编译的时候又是要求你必须提前go get github.com/xx/xx把代码下载到本地的src的,但是从代码管理的角度说呢,第三方的代码不算是我们工程的代码,不应该被提交到我们的代码管理仓库中。那这种咋办,有了go的包管理工具,新浪云要求必须要有Godep这个东西,可以去:https://github.com/tools/godep 这里下载godep,也可以直接用heroku编译好的版本,加入直接放到/usr/local/sbin/.

wget https://raw.githubusercontent.com/kr/heroku-buildpack-go/master/linux-amd64/bin/godep -O /usr/local/sbin/dodep

如果使用godep自动生成依赖

在你的代码路径下执行:

/usr/local/sbin/godep save -r

就可以看到自动生成了Godeps目录,它下面的文件大概是这样的:

[root@vm237147/tmp/f2p2xu8381/src/cow-master]#ls Godeps
Godeps.json  Readme  _workspace

看看那个json文件吧大概长这样:

[root@vm237147/tmp/f2p2xu8381/src/cow-master]#cat Godeps/Godeps.json
{
        "ImportPath": "cow",
        "GoVersion": "go1.5.1",
        "Deps": [
                {
                        "ImportPath": "github.com/codahale/chacha20",
                        "Rev": "ec07b4f69a3f70b1dd2a8ad77230deb1ba5d6953"
                },
                {
                        "ImportPath": "github.com/cyfdecyf/bufio",
                        "Rev": "9601756e2a6b5fa8ca6749ce4f73f6afdd83030d"
                },
                {
                        "ImportPath": "github.com/cyfdecyf/color",
                        "Rev": "31d518c963d22b95d500ab628c1d1d1b8eff2ab9"
                },
                {
                        "ImportPath": "github.com/cyfdecyf/leakybuf",
                        "Comment": "1.0",
                        "Rev": "ffae040843bee2891b6306d1d085c25ca822e72c"
                },
                {
                        "ImportPath": "github.com/shadowsocks/shadowsocks-go/shadowsocks",
                        "Comment": "1.1.4-4-g2b4d9d7",
                        "Rev": "2b4d9d7c839f2939ec6a96cc423dea44319e848b"
                },
                {
                        "ImportPath": "golang.org/x/crypto/blowfish",
                        "Rev": "f18420efc3b4f8e9f3d51f6bd2476e92c46260e9"
                },
                {
                        "ImportPath": "golang.org/x/crypto/cast5",
                        "Rev": "f18420efc3b4f8e9f3d51f6bd2476e92c46260e9"
                },
                {
                        "ImportPath": "golang.org/x/crypto/salsa20/salsa",
                        "Rev": "f18420efc3b4f8e9f3d51f6bd2476e92c46260e9"
                }
        ]
}

关于Procfile

我们的文档中也简单描述了这个东西,应用可以通过代码根目录下的 Procfile 文件指定在容器中运行的程序命令。Procfile 文件每一行声明一条需要运行的命令,格式如下:

type: command

目前type仅支持 web , 也就是web进程,前端负载均衡的请求会被转发给运行这些命令的容器。假如我们的go编译完后二进制名字叫cow那么就可以这么启动

web: cow

如果要在启动的时候带上参数也是可以的

web: cow -rc=/app/rc

我们上传完的代码在哪儿

因为大家暂时还是不能登录到docker的容器中的,所以难免会有这些疑问,我们的代码传上去到底在哪个路径呢,我应用程序启动的时候要指定配置文件去哪弄?我们应用上传完之后默认会在/app这个目录下,这个目录也是docker容器当前用户的home目录,为了印证这个问题,我写了一个http的文件探针,来列一下我们的文件到底是啥样的,主要的代码在这:

r.POST("/ls", func(c *gin.Context) {
        // check dir exist
        dir := c.PostForm("dir")
        dirList, err := ioutil.ReadDir(dir)
        if err != nil {
            c.String(http.StatusOK, "dir not exist")
        } else {
            var ret string = ""
            for _, v := range dirList {
                ret += v.Name() + "\n"
            }  
            c.String(http.StatusOK, ret)
        }  
    })

大家讲这个方法加到我们github那个实例应用的main.go中重新提交部署就可以了。

先看看我本地的目录:

[root@vm237147/tmp/test2/git]#ls -al
total 48
drwxr-xr-x 7 root      root      4096 2015/12/29 16:46:13 .
drwxrwxr-x 4 mingming6 mingming6 4096 2015/12/28 12:16:58 ..
drwxr-xr-x 2 root      root      4096 2015/12/29 13:45:17 .cow
drwxr-xr-x 8 root      root      4096 2015/12/29 14:53:36 .git
drwxr-xr-x 3 root      root      4096 2015/11/26 19:22:52 Godeps
-rw-r--r-- 1 root      root      3426 2015/12/29 14:52:51 main.go
-rw-r--r-- 1 root      root      1305 2015/12/28 12:17:20 memcache.js
-rw-r--r-- 1 root      root      1661 2015/12/28 12:17:20 mysql.js
-rw-r--r-- 1 root      root        24 2015/11/26 19:22:52 Procfile
-rw-r--r-- 1 root      root       726 2015/11/26 19:22:52 README.md
drwxr-xr-x 2 root      root      4096 2015/11/26 19:22:52 static
drwxr-xr-x 4 root      root      4096 2015/12/28 12:18:35 templates

再来发一个请求看看docker中把我们提交的代码放到哪儿去了。

[root@vm237147/tmp/test2/git]#curl 'http://hmh69m3229.sinaapp.com/ls' -d "dir=/app"
.basher
.cow
.profile.d
.release
Godeps
Procfile
README.md
bin
main.go
memcache.js
mysql.js
static
templates

大家可以看到这个app目录就是我们代码提交后保存的目录,其中还有一个bin就是我们go程序编译完之后的目录,我们列一下看看:

[root@vm237147/tmp/test2/git]#curl 'http://hmh69m3229.sinaapp.com/ls' -d "dir=/app/bin"
go-getting-started
templates

果不其然,我们的Procfile是这么写的

[root@vm237147/tmp/test2/git]#cat Procfile
web: go-getting-started

从bin中的go-getting-started大家应该就能发现了吧,这里的Procfile中的go-getting-started启动的就是这样,所以类比的,大家如果程序是其他名字的就将Procfile改成其他名字,如果要启动配置文件的可以将文件放在代码中提交,然后用go的flag传入,在启动时指定到/app/路径就可以了。

结束语

相信看过这个文章再加上实际的操练应该可以初步搞清楚“云容器”是个什么东西,怎么运行起一个go web,后续的文章将会给大家介绍如果在我们的云容器中使用共享存储,如果使用SAE中MySQL、memcache等服务。祝大家2016新年快乐!

如何调试Apache的400错误

诱发原因

此处我们默认导致400的原因是由于我们写rewrite规则错误导致的400错误。所谓400错误就是不合法的请求,意思是服务端已经不知道你请求一个域名加一个路径的含义了。

解决办法

mod_rewite模块支持很多指令,大家可以参考http://blog.chinaunix.net/uid-20639775-id-154471.html。只需要从其中配置上Apache处理rewrite的过程的日志即可,以我实际碰到的一个bug为例,之前的rewrite规则大概是这样的,通过.htaccess文件。

RewriteEngine On

# Some hosts may require you to use the `RewriteBase` directive.
# If you need to use the `RewriteBase` directive, it should be the
# absolute physical path to the directory that contains this htaccess file.
#
# RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]

这个rewrite规则很简单,意思就是把所有的请求都rewrite到index.php脚本处理,但是实际并不是这样,访问的时候一直报400错误,那是什么原因导致的呢,通过在vhost文件的rewrite模块加日志。参见下面的加法:

<IfModule rewrite_module>
        RewriteEngine On
        RewriteLog /data0/logs/rewrite_log
        RewriteLogLevel 9
    </IfModule>

注意看到RewriteLog和RewriteLogLevel,一定要将其等级设置为9才能看到详细的log,这时候我们让Apache重新加载模块 apachectl -k graceful,然后等待日志可以看到:

10.217.88.69 - - [28/Dec/2015:13:28:20 +0800] [op.admin.sae.sina.com.cn/sid#7f4a8b755ca0][rid#7f4a8bcf3338/initial] (2) [perdir /data1/www/htdocs/op.admin.sae.sina.com.cn/] rewrite 'api/login' -> 'index.php'
10.217.88.69 - - [28/Dec/2015:13:28:20 +0800] [op.admin.sae.sina.com.cn/sid#7f4a8b755ca0][rid#7f4a8bcf3338/initial] (3) [perdir /data1/www/htdocs/op.admin.sae.sina.com.cn/] add per-dir prefix: index.php -> /data1/www/htdocs/op.admin.sae.sina.com.cn/index.php
10.217.88.69 - - [28/Dec/2015:13:28:20 +0800] [op.admin.sae.sina.com.cn/sid#7f4a8b755ca0][rid#7f4a8bcf3338/initial] (2) [perdir /data1/www/htdocs/op.admin.sae.sina.com.cn/] strip document_root prefix: /data1/www/htdocs/op.admin.sae.sina.com.cn/index.php -> /index.php
10.217.88.69 - - [28/Dec/2015:13:28:20 +0800] [op.admin.sae.sina.com.cn/sid#7f4a8b755ca0][rid#7f4a8bcf3338/initial] (1) [perdir /data1/www/htdocs/op.admin.sae.sina.com.cn/] internal redirect with /index.php [INTERNAL REDIRECT]
10.217.88.69 - - [28/Dec/2015:13:28:20 +0800] [op.admin.sae.sina.com.cn/sid#7f4a8b755ca0][rid#7f4a8bcfb7c8/initial/redir#1] (2) init rewrite engine with requested uri /index.php
10.217.88.69 - - [28/Dec/2015:13:28:20 +0800] [op.admin.sae.sina.com.cn/sid#7f4a8b755ca0][rid#7f4a8bcfb7c8/initial/redir#1] (1) pass through /index.php
10.217.88.69 - - [28/Dec/2015:13:28:20 +0800] [op.admin.sae.sina.com.cn/sid#7f4a8b755ca0][rid#7f4a8bcfb7c8/initial/redir#1] (3) [perdir /data1/www/htdocs/op.admin.sae.sina.com.cn/] strip per-dir prefix: /data1/www/htdocs/op.admin.sae.sina.com.cn/index.php -> index.php
10.217.88.69 - - [28/Dec/2015:13:28:20 +0800] [op.admin.sae.sina.com.cn/sid#7f4a8b755ca0][rid#7f4a8bcfb7c8/initial/redir#1] (3) [perdir /data1/www/htdocs/op.admin.sae.sina.com.cn/] applying pattern '^' to uri 'index.php'
10.217.88.69 - - [28/Dec/2015:13:28:20 +0800] [op.admin.sae.sina.com.cn/sid#7f4a8b755ca0][rid#7f4a8bcfb7c8/initial/redir#1] (4) [perdir /data1/www/htdocs/op.admin.sae.sina.com.cn/] RewriteCond: input='/data1/www/htdocs/op.admin.sae.sina.com.cn/index.php' pattern='!-f' => not-matched
10.217.88.69 - - [28/Dec/2015:13:28:20 +0800] [op.admin.sae.sina.com.cn/sid#7f4a8b755ca0][rid#7f4a8bcfb7c8/initial/redir#1] (1) [perdir /data1/www/htdocs/op.admin.sae.sina.com.cn/] pass through /data1/www/htdocs/op.admin.sae.sina.com.cn/index.php

如此就可以看到各种内部的转跳[INTERNAL REDIRECT],快速的定位rewrite规则了。

给ServerAlias配置的域名配置单独的访问日志

今天在项目中用到了apache的这种用法,就是同一个VirtualHost上绑定了很多的域名,主要是一个主要的和一个ServerAlias指令配置的别名。但是不同的域名是有不同的作用的,这时候把日志混写在一个日志文件中实在是不方便调试和跟踪。

开始想到的方式是借助apache log format中的%v 和 %V选项,但是发现都不起作用。解释是因为%v只认VirtualHost的权威域名,这个可以参考文档:

  • https://httpd.apache.org/docs/2.2/mod/mod_log_config.html
  • 后来走不通怎么办呢,就试了试%V选项,发现还是一样不行。难道非要把日志重定向给一个脚本才能解决这个问题?还好天无绝人之路,后来使用了如下的方式就搞定了,部分配置参考

    LogFormat "%h %l %u %t %D \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" sinacloud
        ErrorLog     /data0/logs/www.sinacloud.com-error_log
       
        SetEnvIfNoCase Host sinacloud\.com sinacloud_no_www
        CustomLog /data0/logs/sinacloud.com-access_log sinacloud env=sinacloud_no_www

        SetEnvIfNoCase Host www\.sinacloud\.com sinacloud_www
        CustomLog /data0/logs/www.sinacloud.com-access_log sinacloud env=sinacloud_www

        SetEnvIfNoCase Host api\.sinacloud\.com sinacloud_api
        CustomLog /data0/logs/api.sinacloud.com-access_log sinacloud env=sinacloud_api

    大约叫过度自信

    最近观察各种人言论,大体观察出一种奇怪的现象。“凡是我认为不对,别人怎么做都是不对的。”、“先黑你,再说我好。”这种人遍地都是,本来已经把微博的签名改成了“多学习,少吐槽”了,但是还是忍不住要撰文一篇来记录下。

    这就跟现在碰到别人说PHP的时候不知道哪里跳出来的一帮人就开始以反讽的口气说“PHP是最好的语言”一样。一个连PHP都没写过的人为啥有那个胆量去黑人家呢,这件事一直是我匪夷所思的,而且现在的HHVM也不过是PHP的一种实现而已,为啥没人黑了?还是因为这是他们整天吹捧的对象的作品?

    还是要坚决抵制“我做不到这事就是不对”这种傻逼的论调。

    服务器上出现Connection reset by peer怎么办

    众所周知的G*F*W让广大的程序员伤透可心,有时编译代码时候引入了一些google code的代码,这时候在我们墙内的服务器内抓取的时候就出现了“IOError: [Errno socket error] [Errno 104] Connection reset by peer”,那这个时候怎么办呢?

    没关系 http_proxy解救你,来这么一句:

    export http_proxy=http://185.28.193.95:8080/

    就可以了,怎么找这个代理ip?百度搜索关键字“HTTP 代理”就可以了。

    嘈杂的、思绪纷飞的一天

    又快一天的凌晨了,此刻豆瓣电台在放日本的歌曲,http://douban.fm/?start=1381032gf067g0&cid=3381032,米小库也去睡了,我却一点睡意都没有。

    人的一天都在经历好多好多的事情,只是有些事情我们总是不伤心罢了。今天我本也想就这么翻过去了,但是发现还是打开博客记录一下。部门的公开课顺利的举办了;同事也被幸福的求婚了;小姑家也添了一个孙子。以上都是好消息。

    但这个世界总是存在“对冲效应”,我不知道有没有科学的这个理论。但是大概是好事不能发生的太多,让你高兴坏了。大伯再一次进了医院,打通电话的那刻起我就感受到了从县城医院蔓延到心中的绝望,还有求生的欲望。人面临的最悲观的事情莫过于思绪还清晰身体确被判了死刑。此刻之前微博上我们学校那个坚强的白血病校友似乎又跳了出来,我当时是默默的捐了钱的,愿你在那边一切都好。我爱这个世界、也恨透了这个世界的悲凉。晚安。

    写在寒衣节(2)

    今天肯定不是一个普通的星期六。因为好多人都在难过中度过,这其中包含了康定和日本的地震还有我大家庭的“地震”。

    从没想到“癌症”这个东西会在我的大家庭中,自今年五月份接到大哥说要回家的电话就知道今年就肯定注定不能平静。愿大伯能挺过这个难关平安走过2014。

    写在寒衣节(1)

    今天是中国的一个传统节日,“寒衣节”。我也是今天才第一次听到这个节日的说法,晚上和米小库打电话的时候她说斛兵塘边有几个人老人在烧纸钱,联想一下上午去市场买菜的时候也看到从来没有过的摊位在卖纸衣服和纸钱。不禁感叹原生一天中发生的一些本来可以不多想的事情都可以串起来,生活本是一本书。

    晚上吃完饭后看到姐姐的微信,才知道家里又有人不行了,下午还在和米小库感慨这人世间的纷纭往事,最终给后人留下的都只有一个个的坟头。只能感慨命运弄人,为什么偏偏选择在这样不平常的一天给人生又添上这么多的堵。想起了沈从文的《边城》,“翠翠明白了捐钱人的怜悯,背过身子去拉船。愿死了的到西方去,活着的永葆平安。”

    我自小就和姐姐一起在离家大约两公里远的地方上小学,之后上初中的时候大约把这个距离再缩大一倍。那时候我总是迈着我的小短腿在一条路上走了七年,我想这辈子要是问我印象最深的是那条路,我想永远也忘不了那条自老家到学校的小道了。现在大概已经杂草丛生,无处下脚了。

    在上学的路上总会路过那些固定的地点,有一个个的稻田,有一条小河,还有一个约三米的小桥。这之间还会路过一户姓方的人家,今天和米小库回想起来才感慨这家人似乎充满了可以说成故事的色彩,我想大概也没有人给他们整理成故事放到互联网上吧,那今天就把他们的故事整理一下,也便于自己以后在某年某月想起那些人。我愿岁月可以回头,好让我有个照相机,拍下那些人好给自己更丰满的回忆。

    按辈份来说,这个方姓人家的主人应该是我“爷爷”级别的,按我们当地的风俗来称呼叫“表爷爷”,虽然我到现在还不知道跟我们有什么亲戚关系,可能就是天生的邻居吧。按照安庆浓郁的亲戚随礼氛围,家里有什么红白喜事都是要去送点东西或者钱然后吃一顿饭的。我就称呼他为方爷吧,他的一生应该经历了很多,出生在民国时期,从历史来看应该经历了新中国的成立,到自然饥荒的时期。从我了解的情况来看他一生是结过两次婚的,前一个应该有一个孩子但是后来应该不在自己身边长大,可能是分来后跟了女方,具体离婚的原由不知道,这些都来自我奶奶的口述。后面娶的这位妻子是一个听觉有障碍的人,但是也不是完全听不见,只是说话的声音必须要很大才能听到。两人总共生了三个子女,最大的是个女儿叫凤霞,中间的是个儿子叫阳敏,最小的也是个女儿叫月梅,在我看来除了最小的女儿外其他人的生活都可以排成一部剧。

    先在来说说他子女的故事吧,大女儿前后应该嫁了四次人。我不能给这个人的人生贴上任何的标签,因为每个人都有每个人的活法,特别是新时代一个不起眼的社会人。大约在她二十几岁的时候,先是嫁给了当地的一个手艺人,和她的第一任丈夫育有一子,估计按常规的生活这样可能就平平淡淡的走完这一生了,但是不久感情就破裂了,然后她就被万恶的人口贩子骗到了福建。在这段时间内她和她的丈夫生育了一个儿子,这个孩子和我姐姐差不多大小,应该出生在87年左右,出生在这样的家庭也注定了他孤苦的少年时代。妈妈不见了,爸爸又再婚了但是后妈如广大的电视剧中的剧情,对这个前妻的儿子百般的刁难,再加上后来她自己有了孩子就对他更差了。好在命运总要在这个时候给出一点补偿,给了他一幅聪明的大脑和一个疼她的奶奶。他奶奶后来一直靠捡破烂给她的孙子交学费,这个老人一如伟大的奶奶,总是自己再苦也要给自己的孙子更多。后来听到的消息是他考上了安大,但奶奶还是去世了由于癌症,我能想象这个男孩最终的痛苦,但他没有什么怨恨,还是一如既往的认着他的妈妈和爸爸。

    据说是被骗到福建的某个小地方,被卖到一个傻子家庭,和一个傻子结了婚,但幸好还有个智力健全的公公,若干年这么平静的过去了,最终她和他的傻子丈夫倒是生育了三个孩子,万幸的是这些孩子没有傻子了。但是不知道是出于对故乡的怀念还是其他原因最终她还是狠心抛弃了她的三个孩子和她的傻子丈夫回到了家里,这时她的小妹都已经长大成人出嫁了,弟弟的孩子都在上小学了。不管如何对于自己的父母和第一个孩子也算是个交代了,不能就这么不明不白的就消失了这么多年。随后回家后又再婚了一次,这次结婚的对象是一个亡妻的男人,带着一个小孩,按我奶奶带着感情色彩的话来说,这叫“不管自己的孩子却去帮别人带孩子”,但按现在的纲常和少数派一直在推动的个人幸福论来说我也觉得可以接受。这样的生活大概维持了几年吧。由于这个事情还是发生在我念高中之前,我每天还是会路过他家,不能家里的孩子除了孙子外又来了一个没有血缘关系的外孙。不过这个孩子倒是和孙子年纪相仿,我的印象中这个外公从来没有叫自己的第一个外孙来自己家吃过饭,可能是他对第一个女婿充满了失望吧。但家乡总是流传着一句话叫“一代管一代”,对这个行为我至今仍然难以理解。这时候的方家似乎出奇的热闹,每逢佳节总会儿孙满堂,两个女婿总是骑着摩托车带着一家来到这个家。这时候的他似乎也特别高兴,每次路过他家都是在准备晚饭,他总是对着他那有点聋的妻子大声的说话。但这个女儿似乎一如既往的让他不省心,好景不长,大女儿的这段感情又破灭了,原因在于她自己,在婚姻期间很随性的就出轨了,而且出轨的对象还是他的工友,也是一个做砖匠的工人。大女儿就这样开始了她的第四段婚姻,这时候发生的事情我已经初中毕业了,之后再也没有路过他们的家门了。但大女儿的故事可以缩影为一个一直在追求自己幸福的人但是还是在随波逐流,远离了自己所有的孩子最后在家里当期了“奶奶”,因为最后一个丈夫的儿子都已经结婚生了孩子。

    对于这些子女的婚事,他似乎没有看的很重,因为从我和他认识的这么多年,我以幼小年纪的世界观看起来他一直是一个乐观的人。每天都笑呵呵了,似乎也很少有烦心的事情。他算是一个“吃国家饭的人”,毕竟不是旧时代的地地道道的农民,从他家的贴画看出,他是一个退伍的军人。每到发工资的时候他也会穿上他的皮鞋带上手表去小镇上的信用社领取他的工资,而每次中午我回家吃饭的时候他都会拎着一些吃的回来,这其中大概有他最喜欢的紫菜,而且他家的紫菜汤从来都没有鸡蛋。原因无法理解,因为我的世界观就是紫菜一定是和鸡蛋在一起的。他也会慷慨的拿出他的吃的给我,还会叫我到他家坐坐喝点水再回家。

    相比于大女儿,儿子似乎也没有让他省心,从小儿子就是一个“浪子”,后来初中毕业后估计就出去闯荡了,应该后来大家知道的版本就是去了福建,和当地的一个女人结了婚,并且那个女人给他生了一个孙子。但这个女人似乎也是一个爱追求自己幸福的人,家里的版本是这个女人最终还是跟一个大老板走了,从此温馨的家庭就支离破碎了,还好没有带走她的孩子。记得小时候家里周围的妇女们都是去家里旁边的一个池塘洗衣服的,那时候我有次也跟着去了,恰巧这个小孩的奶奶也带着孙子去洗衣服了,这个小孩天生比较乖巧,有着一对招财耳。但妇女们总是顾忌不了那么多,这么小的小孩都会成为她们的调侃对象,她们问道“你恨不恨你妈妈?”,这个问题在我这么短的人生中就听到了很多次,真是不敢相信。当时我很兴奋的在一旁捉小虾玩没有注意到这个小孩的眼神,但他应该没有回答。后来,他也上学了,我每天都带着他,但我知道他肯定恨透了“妈妈”这个字眼。但还好这个我印象中的小男孩没有让我失望,成绩很好。儿子也是几年不回家,理由是在外没有赚到什么钱不能回家过年。老两口就这么一直拖拉着他们的孙子,但还好他们的生活也还有个寄托。现在,他们的儿子似乎又重新找了个对象,应该又有了一个孩子吧,现在的经济条件应该是比之前好多了。但是在条件好了之后过年依然不回家这个我到现在还是很难理解。

    小女儿过着比较正常的人生,我读小学的时候她就上初中了,但那时候考高中还是挺难的,印象中她没有考上,后来就做了我们那最热门的终止学业后的工作,做裁缝。在不久之后就+给了离他家约两里路的一户人家,生了小孩,时常看见她带着孩子在家。

    他们家还有很多特别有意思的事情,例如总是养猫和狗,前前后后养的猫和狗的数量我都记不清了。但猫总是很慵懒,每次路过都在睡觉,狗总是很友好,因为我天天路过,倒也成了和它们最亲近的人,他们家之前还养过鹅、兔子动物数不胜数,姐姐总是怕他家的鹅,因为被咬过一次。再有印象最深的可能就是他妻子的“时尚”了,我们本是一个在务农的小乡村中,但是总是每天穿金戴银的,而且他自己几乎不去农田里干活,所有的体力活都是花钱找人做的。

    他自己还有一个弟弟,这个弟弟我也不好定性称为什么人,但是他的职业确实是乞讨。我不知道为什么一个正常的家庭为什么会产生这么一个角色,大概是因为他好吃懒做吧,平时住在哥哥家的平房中,有自己的一个小房间,几乎从来不打扫,都是他嫂嫂帮忙洗一洗被子之类的。每次都看到他穿的很破烂的拿着他的谋生物件出门乞讨,但是过了一段时间还是会定期的出现在家里。按他嫂嫂的说法他不傻,只是好吃懒做,但在我上高中的某年过世了。死在了家里对他来讲也是一件幸福的事情吧。但他哥从我的眼中看到的似乎没有对这个弟弟的爱,因为在我看起来他似乎是他的负担,也是一个赚钱的工具。但这个人还是让我想起了自己的一个家人,最终也是一样的下场,但是他不是靠乞讨为生的。有些兄弟总是到人生的最后一刻才会相认,不知道为什么,可能是人的自尊在作祟吧。

    死亡这件事情,人的一生中总要面对,但大学里一个打回家的电话中被告知这个方爷走了的消息还是震惊了一下,印象中这是一个身体很好的人而且心态乐观。他总是有一副见过世面的自豪感,和其他人聊天也总是在不听的说自己的过去,说自己当兵的故事。我本想不起这个人,但下午和米小库的聊天还是勾起了回忆,不禁感叹纷纭往事如今却一个个变成了一个个坟头出现在了自己的生命中。这个时常穿着军绿色夹袄的人似乎还活在自己眼前。如今只剩下还是天天穿金戴银的老人一个人孤独在家等着孙子放月假回家,儿女们总是有忙不完的事情。但庆幸的是,如今儿子肯定会回家过年了。有时我们标榜的价值观可能很难是普适的价值观,愿每个人幸福快乐。

    也看央行降息

    今天上微博上热闹的事情比较多,给大家震惊最大的无疑是央行的降息了。在下班的班车上同事们都在微信群中讨论这个事情,晚上回来关注微博上的各种言论到现在,发现了很多很多有意思的解读。但是由于我也不是学经济的看不懂其中的原委,但是凭着自己的直觉我觉得这是一次一石多鸟的测试,先来看一条央行微博在11月19号晚上发布的微博:

    从这个微博的只言片语中其实就可以看出来今天的行为了,很多人的观点是说这次是因为高层受不了当前的经济增长速度了,其实我没记错的话是不是上个月的经济增速就已经跌破7了,但是也没看见高层发布什么言论出来,该查反腐还是反腐,改鼓励中小企业发展还是鼓励。还有很多人说这是对房地产的帮助,我看也不尽然,说实话现在大部分的年轻人对中国的房地产真的持悲观的态度,这种态度一旦形成,很难通过很简单的刺激行为就能消灭,我不觉得房地产行业今年的业绩会随着这次央行行为而发生改观。

    但愿是真的在帮助企业,真正的发展经济,可持续的发展还是要靠真正的企业创造GDP,靠炒出来的经济肯定是有很大问题的,可现在真正的问题恐怕在于大家都明白这个道理但是还是想着在房地长萎靡之前把自己的钱弄进去滚一笔出来。

    最近一张ps的图

    最近也在玩photoshop的图片处理,不得不感叹这个软件的功能强大,任何一个功能估计都能一个研究生发篇文章了。更何况人家还直接把理论和工程密切的联系了起来。

    这个ps的效果就是“镜头模糊”,可能比较低级,但是是鄙人第一次处理风景图片还是发上来纪念一下。

    顺便说一句,“羽化”很重要,技巧是看处理的图片的尺寸,一般在5px左右就可以,可以让处理完的结果看起来更真实。