PM2 with socket.io

一般比较喜欢通过 PM2 来管理 node application,部署时一般也会使用 -i max 参数来打开尽可能多的进程,多数情况下这样做并不存在任何问题。

但是,socket.io 使用 XHR-Polling 方式来验证 SID,进而建立链接时,即使使用了 socket.io-redis,依然是无济于事的。因为 socket.io 需要 sticky load balance 固定到同一个进程上。官方提到一些方法 http://socket.io/docs/using-multiple-nodes,可以参考。基于此,也有另一些包,可以解决问题,比如 https://github.com/PROGrand/sticky-socket-cluster

总之,不能用简单用 PM2 来管理 cluster 了。PM2 和 socket.io 双方有一些踢皮球,所以这事儿暂时无解。哈

How to start pm2 server in a docker container

直接在 docker 的 container 中运行 PM2 可能会遇到以下问题:

1
PM2 dameon PID = 1
0 with /.pm2/pm2.log file not found

这是因为 /.pm2 目录不存在造成的。可能很多人此时会想到去创建该目录,事实上是不必要的,比较好的做法是使用官方提供的 dump 命令。

运行 PM2 的 Dockerfile ,可以参考:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
FROM node:0.11.13
# or just node, without tag

RUN npm install -g pm2
RUN pm2 dump
# dump will start pm2 daemon and create everything needed

VOLUME ["/srv/apps", "/srv/logs", "/srv/server.json"]
# don't put the files in docker container, user -v

EXPOSE 3000

CMD ["pm2", "start", "/srv/server.json", "--no-daemon"]
# no daemon mode for docker

搞定。

Dash is not bash

在一些 docker 官方 Image 中,执行一些 .sh 文件的时候遇到了一些奇怪现象,比如:

1
2
3
# Run something like:
[[ $ABC =~ regexp ]]
#> [[: not found

其实是因为此 Image 中 sh 并非 bash,而是 dash:

1
2
ls -l /bin/sh
#> /bin/sh -> dash

此时,只需重置 sh 就好了:

1
2
rm /bin/sh
ln -s /bin/bash /bin/sh

不过,在 docker image 里,还是不建议执行 .sh 文件。所有事情都在 host 上完成,之后 -v 共享目录给 docker container 为好。

参考

Use SSH agent forwarding in your private network

大量云服务开始提供可供定制的私有网络功能来组织你所购买的 VPS,如果此时还通过直接链接每台机器的方式来管理,就太浪费资源和极为的不安全了。

以 qingcloud 产品为例,可以通过 GRE 隧道或者 VPN 等手段来实现安全登录和管理。但在一些条件不具备的情况下,采用内控堡垒主机(运维堡垒主机,Bastion Host)方案不失为一个好的方法。

将私有网络(内网)中的一台机器作为堡垒主机,将其 SSH 端口映射向公网某端口,打开该端口的防火墙 TCP 设置。此时,公网只能访问该堡垒主机,登录后,再通过该机登录其他服务器,从而即实现对了公网对其他服务器的隔离,有能够方便管理所有服务器。

方案容易,部署也不麻烦,但这里引发一个问题—— SSH Key 的问题。如果在堡垒主机上使用任何 Key 一旦堡垒主机被攻破,那么其他服务器就是“白给”状态,所以这里可以采用 SSH agent 来“中转” Key。

其实只要比常规方法多 -A 参数就可以实现 Key 中转了:

1
ssh -A user@your.server.ip

使用 SSH config 的话,增加 ForwardAgent 属性:

1
2
3
Host any_name_want
HostName your.server.ip
ForwardAgent yes

此时,访问内网的其他服务器时,形如:

local —- ssh -A —-> Bastion Host —- ssh —-> Server 1 / 2 / 3 /…

当然,在所有服务器上使用的都是你本地 Key 的公钥

但还没有结束,由于 Bastion Host 并不运行正在的服务,在其他服务器上需要部署服务,尤其是通过 git 这类方式部署的时候,又有 Key 的问题了,所以改进一下:

local —- ssh -A —-> Bastion Host —- ssh -A —-> Server 1 / 2 / 3 /…

是的,就是 SSH agent forwarding 两次。

OK,done!

主要实现摘自:
SSH agent forwarding 的應用

No more sudo for using docker

操作 docker 的时候每次都需要 sudo 来提升权限,比较麻烦,可以有一个简单的方法来解决:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 如果 docker 用户组不存在,那么先添加docker用户组。
# 事实上例如在 CentOS 上使用 `yum` 安装的 docker,已经存在 docker 组
sudo groupadd docker
# 把当前使用的账号添加到 docker 组
sudo gpasswd -a username docker
# > Adding user username to group docker
# 然后 restart docker
sudo service docker restart
# 完成,但此时还是旧的环境状态,先注销
exit
# 再次登录
ssh you.server.ip
# 试试
docker images
# > REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
# Done!

cgconfig service error when the docker starts

当启动 Docker 服务的时候,遇到如下错误:

1
2
3
4
Starting cgconfig service: Error: cannot mount cpuset to /cgroup/cpuset: Device or resource busy
/sbin/cgconfigparser; error loading /etc/cgconfig.conf: Cgroup mounting failed
Failed to parse /etc/cgconfig.conf [FAILED]
Starting docker: [ OK ]

可以使用 cgclear 命令,清理一下。

之后记得先停止 Docker ,再启动。

1
2
3
cgclear
service docker stop
service docker start

PS. OS = CentOS

Atom Package Development

尝试了一下给 Atom 开发 Package,感觉还很不成熟:

  • 文档缺乏
  • 界面控件缺乏
    • 目前在 package setting 页面只提供了 text editer 和 checkbox
  • 非 CoffeeScript Coder 不友好
    • 官方以 CoffeeScript 为例在做介绍
    • 大部分现有 package 都是 CoffeeScript

但也有很多优点:

  • 总体对 JavaScript Coder 友好
    • 基于 node.js 和 chromium
    • HTML / CSS 为界面渲染引擎
  • apm 包管理非常好用
    • 类似 NPM
    • 方便安装本地开发的包
    • apm publish即发布
  • 容易调试,因为可以调出 chromium console

速成方法

官方版看这里 https://atom.io/docs/latest/your-first-package
JavaScript 版看这里 http://blog.fxndev.com/create-your-first-atom-package-in-js/

一些技巧

  1. 任何在 Atom 里安装的 package 都可以在其设置里面点击 “Open in Atom” 按钮在 Atom 里直接打开源码所在目录直接查看源码。

  2. 代码另存后,很容易在本地安装,只需:apm link package/path

  3. 通过 cmd-shift-p (OSX) or ctrl-shift-p (Linux/Wndows) 里的 Window: Reload 命令即可重新加载任何 package 的改动。

  4. 像打开 Chrome 浏览器里的 console 快捷键一样,可以打开 Atom 的 console。

PS. Mac 下 APM 无需安装,运行过 Atom 后即存在了。


End

对于 Atom 的发展,还是静观其变吧,目前还不是很推荐作为生产工具(效率略低)。

本文写于 Atom with Markdown Writer.

NPM and node-gyp

pm2 中会使用到 fsevents,node-gyp rebuild fsevents 时,会遇到下面这样的错误:

1
user "root" does not have permission to access the dev dir

网上找到的讨论,说 node-gyp 不能用在 sudo 下,由于 Mac 上 pkg 安装的 node 需要 sudo 执行 npm,所以这样:

1
2
sudo chown -R `whoami` ~/.npm
sudo chown -R `whoami` /usr/local/lib/node_modules

之后就不再需要 sudo 安装 npm 了。

重新安装 pm2 ,到了 fsevents 时, node-gyp rebuild 能运行了,但到了一半,错误变成这样:

1
2
3
4
5
6
7
8
make: *** [Release/obj.target/fse/fsevents.o] Error 1
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack at ChildProcess.onExit (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:267:23)
gyp ERR! stack at ChildProcess.EventEmitter.emit (events.js:110:17)
gyp ERR! stack at Process.ChildProcess._handle.onexit (child_process.js:1046:12)
gyp ERR! System Darwin 13.3.0
gyp ERR! command "node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"

但是安装是成功的…… pm2 可以正常使用。

为探究竟,费尽半天辛苦,发现原来是 node 0.11.13 的问题……可以看这里https://github.com/pipobscure/fsevents/pull/26

无言以对。