目前赛亚测试服务器的现状就是一台服务器上跑的服务非常多,我们把所有服务都 Dockerize 化之后通过统一的一个 Nginx 反向代理容器对外开放,其中下层的容器名作为反向代理的域名。

server {
    listen 80;
    server_name project.domain;

    location / {
        proxy_set_header        Host $http_host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_pass      http://container:80;
        proxy_redirect  off;
    }
}

我们遇到的第一个问题就是当其中某个下层容器因为各种原因启动失败的时候,Nginx 就会因为该容器名对应的域名解析失败导致无法重启,解决的方法就是把 proxy_pass 的值传入变量,此时 Nginx 就不会在启动的时候解析这个域名了。

server {
    listen 80;
    server_name project.domain;

    location / {
        proxy_set_header        Host $http_host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

        set             $remote container;
        proxy_pass      http://$remote:80;
        proxy_redirect  off;
    }
}

我们遇到的第二个问题是要在测试服务器上做个简单的滚动部署,让测试人员无缝切换,大概就是每个服务搞两个容器,用 Nginx 负载均衡一下,部署的时候先更新第一个容器再更新第二个容器。这个时候我们遇到的问题是在 upstream 这个上下文中是不能像 location 上下文这样用变量代替域名的,直接写域名又会导致 Nginx 启动依赖下层容器的问题。研究了一个晚上,发现用 unix socket 多转一层可以 workaround。

server {
    listen unix:/var/run/socket-1.sock;

    location / {
        proxy_set_header        Host $http_host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_pass      http://container-1:80;
        proxy_redirect  off;
    }
}

server {
    listen unix:/var/run/socket-2.sock;

    location / {
        proxy_set_header        Host $http_host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_pass      http://container-2:80;
        proxy_redirect  off;
    }
}

upstream upstream {
    server unix:/var/run/socket-1.sock;
    server unix:/var/run/socket-2.sock;
}

server {
    listen 80;
    server_name project.domain;

    location / {
        proxy_set_header        Host $http_host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_pass      http://upstream:80;
        proxy_redirect  off;
    }
}