尝试使用 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

广告
将在 10 秒后关闭
bannerAds