尝试使用 Nginx 的 reuseport(SO_REUSEPORT)功能。通过 Docker Compose 进行实验
nginx 的 reuseport 选项是什么意思?
在Nginx 1.9.1版本中引入了一个新功能,可以启用名为SO_REUSEPORT的套接字选项。
SO_REUSEPORT 是什么?
此项功能使得在Linux Kernel 3.9及以上版本中,可以将一个端口绑定给多个进程。
SO_REUSEPORT(自Linux 3.9起)
允许多个AF_INET或AF_INET6套接字绑定到同一个套接字地址。在调用套接字上的bind(2)之前,必须在每个套接字上设置此选项(包括第一个套接字)。为防止端口劫持,绑定到相同地址的所有进程必须具有相同的有效UID。此选项可用于TCP和UDP套接字。
换句话说,可以快速且无停机时间地创建使用相同端口的其他进程。因此,对于加速和无停机时间的部署非常方便。
我尝试了一下Docker。
在主流发行版中,设置默认为3.9或更高版本的很少。
顺便说一下,截至到2015年10月13日,docker-machine的VirtualBox驱动程序所提供的boot2docker内核版本为Linux v4.1.10 (AUFS v4.1-20151012)。您可以在以下链接找到更多信息:https://github.com/boot2docker/boot2docker/releases
我决定试试看,因为我觉得这可行!在我正在使用的OS X上,使用Docker on boot2docker配置。
为了方便起见,我决定使用docker-compose(原名fig)来简化操作。
如果只是普通的使用nginx,发送HUP信号就可以重新加载(优雅重启)了,这应该足够了。但是,特别是在Docker的情况下,经常会出现”希望替换整个容器”的情况,这种情况可能更适合,比如整个容器集群的绿蓝部署。
准备好的文件。 de .)
只需要三个选项。
-
- docker-compose.yml
-
- nginx の default.conf (reuseport を ON にしたもの。 HTTP の応答は単に “OK” とだけ返答する )
- test.sh (一括で実行するシェルスクリプト)
使用主机网络配置启动3个nginx进程。
由于使用了reuseport选项,所以它们都在80端口等待连接,
首先建立连接并进行正常的HTTP响应。
按下Ctrl-C键退出。
nginx_1:
image: nginx
net: host
volumes:
- ./conf.d:/etc/nginx/conf.d
ports:
- "80:80"
nginx_2:
image: nginx
net: host
volumes:
- ./conf.d:/etc/nginx/conf.d
ports:
- "80:80"
nginx_3:
image: nginx
net: host
volumes:
- ./conf.d:/etc/nginx/conf.d
ports:
- "80:80"
server {
server_name localhost;
listen 80 reuseport;
location / {
return 200 'OK';
}
}
#!/bin/sh
MACHINE="$1"
eval "$(docker-machine env "$MACHINE")"
TARGET_HOST=$(docker-machine ip "$MACHINE")
docker-compose up -d
while sleep 1; do
curl -fsSL "$TARGET_HOST"
done > /dev/null &
SUB="$!"
docker-compose logs
kill "$SUB"
docker-compose stop
docker-compose rm -f
执行案例
$ ./test.sh default
Creating nginx2_nginx_2_1...
Creating nginx2_nginx_3_1...
Creating nginx2_nginx_1_1...
Attaching to nginx2_nginx_1_1, nginx2_nginx_3_1, nginx2_nginx_2_1
nginx_3_1 | 192.168.99.1 - - [13/Oct/2015:12:30:54 +0000] "GET / HTTP/1.1" 200 2 "-" "curl/7.43.0" "-"
nginx_2_1 | 192.168.99.1 - - [13/Oct/2015:12:30:55 +0000] "GET / HTTP/1.1" 200 2 "-" "curl/7.43.0" "-"
nginx_3_1 | 192.168.99.1 - - [13/Oct/2015:12:30:56 +0000] "GET / HTTP/1.1" 200 2 "-" "curl/7.43.0" "-"
nginx_2_1 | 192.168.99.1 - - [13/Oct/2015:12:30:57 +0000] "GET / HTTP/1.1" 200 2 "-" "curl/7.43.0" "-"
nginx_1_1 | 192.168.99.1 - - [13/Oct/2015:12:30:58 +0000] "GET / HTTP/1.1" 200 2 "-" "curl/7.43.0" "-"
nginx_2_1 | 192.168.99.1 - - [13/Oct/2015:12:30:59 +0000] "GET / HTTP/1.1" 200 2 "-" "curl/7.43.0" "-"
nginx_1_1 | 192.168.99.1 - - [13/Oct/2015:12:31:00 +0000] "GET / HTTP/1.1" 200 2 "-" "curl/7.43.0" "-"
哦,nginx1_1、nginx2_1、nginx3_1正在交替响应。感觉不错。
在实际的应用中,
-
- 新しいクラスタをデプロイ
- 旧いクラスタの nginx コンテナに QUIT シグナルを送る (graceful shutdown)
我认为最好按照这个顺序进行。
随便聊聊
此外,听说 HAProxy 会自动启用 SO_REUSEPORT。
https://github.com/haproxy/haproxy/blob/3cd0ae963e958d5d5fb838e120f1b0e9361a92f8/src/proto_tcp.c#L792-L798
http://diary.sorah.jp/2015/02/09/20150209
https://github.com/haproxy/haproxy/blob/3cd0ae963e958d5d5fb838e120f1b0e9361a92f8/src/proto_tcp.c的第792-798行
http://diary.sorah.jp/2015/02/09/20150209