小Cの已经记不起来的博客

Nginx 反向代理 灰度发布 配置详解

最近公司项目要上灰度发布,本来想着找个现成的网关方案,什么 K8s + Istio 之类的,结果一算成本和复杂度,算了,咱们这小体量,Nginx 自己配一下就够了。折腾了两天,踩了几个坑,把实测可用的方案记录一下,免得下次又忘了。

什么是灰度发布

简单说就是新版本代码部署上去之后,不是一刀切把所有流量都切过去,而是先放一小部分用户(比如 5%)到新版本上,观察个几天没问题,再逐步放大比例,最后全量。这样做的好处很明显,万一新版本有 bug,影响面也只有那一小撮人,不至于全线崩盘。

常见的灰度策略有几种:按比例随机分流、按 Cookie 分流、按 IP 分流、按 Header 分流。下面挨个说说怎么在 Nginx 里实现。

方式一:按比例分流(最简单粗暴)

利用 Nginx 的 split_clients 模块,按哈希值把流量切分:

http {
    split_clients "${remote_addr}${uri}" $backend_pool {
        10%     backend_new;
        *       backend_old;
    }

    upstream backend_new {
        server 192.168.1.10:8080;
    }

    upstream backend_old {
        server 192.168.1.20:8080;
    }

    server {
        listen 80;
        location / {
            proxy_pass http://$backend_pool;
        }
    }
}

这里用的是 remote_addr 加 uri 做哈希,好处是同一个用户访问同一个页面,基本会稳定落在同一个后端上。要是只写 ${remote_addr},多个人共用一个出口 IP 的情况(比如公司内网)就一起被切过去了,这个看业务接受度吧。

改比例的时候直接把 10% 改成 30%、50%,reload 一下就行,很方便。

方式二:按 Cookie 分流(推荐给内部测试用)

如果想让指定的测试人员先体验新版本,Cookie 方式最省心:

map $cookie_gray_version $backend_pool {
    default     backend_old;
    "v2"        backend_new;
}

server {
    listen 80;
    location / {
        proxy_pass http://$backend_pool;
    }
}

测试的同学在浏览器里设置一下 Cookie(控制台里敲 document.cookie="gray_version=v2" 就行),刷新页面就进新版本了,其他人完全无感知。放量的过程就是通知更多人加上这个 Cookie,等验证得差不多了再切比例。

方式三:按 Header 分流(配合网关或 App 用)

App 端或者有自建网关的场景,一般习惯用 Header:

map $http_x_gray_tag $backend_pool {
    default     backend_old;
    "beta"      backend_new;
}

逻辑和 Cookie 版一样,只是判断的字段换成了 X-Gray-Tag。

会话保持的问题

这里有个大坑要提醒一下:如果你的应用是有登录态的,灰度切过去之后,用户的 session 得两套后端都能认,不然用户会被莫名踢下线。我们当时就遇到这个问题,新版本把 session 存储从本地改成了 Redis,结果灰度期间新版本读不到旧 session,用户一刷新就掉登录。

解决办法要么提前统一 session 存储,要么在灰度期间用 proxy_cookie_path 之类的手段做点兼容,总之提前想好,别上线当天手忙脚乱。

一些细节

整体下来,Nginx 做灰度发布完全够用,配置也不复杂,小团队没必要一上来就上重型网关。

评论

还没有评论。

发表评论

提交后评论将经过自动审核,审核通过后公开展示。

未在播放