9月 192018
 

缘起:

docker stop 时往往会比较慢,起原因多半是docker 容器的init进程没有正确处理信号所致;docker stop的行为为: 先发送一个SIGTERM(15) 信号给init进程,如果一段时间(默认10s)后,依然没有退出,就直接发送 -9 信号,常常我们会登上10s,最终,进程的退出依然是仓促的;所以,实现一个好的init进程非常重要。

想用bash写一个docker 的init进程,当收到SIGTERM信号时,通知容器中的其他进程退出,其他进程退出后自己再退出,这样的话,其他进程可以有时间优雅退出,而且stop操作还可能很快完成。

版本1:

实际并不凑效; 原因: bash 在执行外部命令的时候,是不处理信号的

 

改进:

不足:当有信号到时,依然要等sleep 睡足才能处理信号,如果每次sleep 时间足够短,则总是启动sleep进程也非常不优雅,本身总是看到一个sleep进程已经够闹心的了

 

改进:

优点:

  1. 看不到sleep函数了
  2. read line 并不消耗多少资源
  3. 虽然 read 函数是阻塞的,但是却不影响bash实时处理信号

缺点:

  1. 创建容器时需要 -it 选项,因为bash标准输入需要是正常的,才能是的read不会失败而正常阻塞,否则,read会一直失败,导致死循环占用100% CPU ; 安全一些的做法是,发现read失败直接退出

 

测试脚本:

执行该脚本,然后发送信号15给bash进程,发现:

  • 当执行到sleep 10 的时候,不能实时处理信号
  • 当阻塞在read时,可以实时处理信号
 Posted by at 下午 5:08
9月 122018
 

对于http负载均衡,往往有超时限制;对于tcp负载均衡,往往不做源地址转换(无法通过配置的方式设置为需要源地址转换),对于如下部署方式:

APP如果调用自己的话,可能服务器A发起请求,经过负载均衡后,又落到了服务器A自身,这是,由于负载均衡没有做源地址转换,所以,A的回包是发现目的地址就是自己,就不需要离开本机了,然而这种没有经过源地址转换的回包是不会被认可的,所以,这种部署方式存在较大弊端,尤其是一个服务器上部署多个应用时,应用之间的频繁调用就必然会遇到这个问题。

 

改进方案:

 

如果请求发起总是在APP上,则上述模式工作的会比较好;

但是,还有情况需要考虑,nginx做内部重定向的情况也是非常常见的,当访问a.i.phpor.net 时,很可能需要nginx直接内部转发到b.i.phpor.net ,这是,请求发起者是nginx,为了节省资源,b.i.phpor.net 也是使用的同样的负载均衡和nginx,于是,又出现了前面所讨论的问题。

 

再次改进,确保nginx不会重定向请求到负载均衡,毕竟还是要回来,索性在nginx上稍微麻烦一些,直接转发到自己,或者nginx上将所有自己能提供的服务的域名都解析到127.0.0.1

 Posted by at 下午 4:43
9月 032018
 

如图:

Local B想访问Remote B的80端口,但是由于网络限制,访问不到,但是,Local A可以访问Remote A的22端口,于是:

这样就可以在Local A上listen一个80端口,将接收到的数据包转发给Remote B的80端口

由于listen的端口在本地,所以叫做本地端口转发。

 

同样是Local A可以主动访问Remote A,但是Remote A不能ssh访问Local A,我们想让Remote B能访问Local B的80端口,如何做呢?(注意: 这里并不是上述逻辑的一个翻版)

命令:

这样就可以在Remote A上listen一个80端口,将接收到的数据转发到Local B的80端口;

由于listen的80在远端,所以叫远程端口转发

 

相关原理:

当通过端口转发创建虚线中的连接时,local A和remote A 之间并不会创建一个新的tcp连接,而是在原有tcp连接上创建了新的channel,这个可以在ssh 时 -vvvv看到相关信息

 Posted by at 下午 4:56