可见负载均衡的列表中,9000端口的服务实例已经置为down,此时疯狂请求,只输出hello world by 127.0.0.1:9001,可见9000端口的服务实例已经不再参与负载。重新上线9000端口的服务实例:
curl -X PUT -d '{"weight":1, "max_fails":2, "fail_timeout":10, "down":0}' :8510/v1/kv/upstreams/app/127.0.0.1:9000再疯狂请求,发现hello world by 127.0.0.1:9000和hello world by 127.0.0.1:9001交替输出。到此可以验证动态负载均衡是成功的。此时再测试一下服务健康监测,通过kill -9随机杀掉其中一个服务实例,然后观察/upstream_status端点:
疯狂请求,只输出hello world by 127.0.0.1:9001,可见9000端口的服务实例已经不再参与负载,但是查看Consul中9000端口的服务实例的配置,并没有标记为down,可见是nginx_upstream_check_module为我们过滤了异常的节点,让这些节点不再参与负载。
总的来说,这个相对完善的动态负载均衡功能需要nginx_upstream_check_module和nginx-upsync-module共同协作才能完成。
服务平滑发布服务平滑发布依赖于前面花大量时间分析的动态负载均衡功能。笔者所在的团队比较小,所以选用了阿里云的云效作为产研管理平台,通过里面的流水线功能实现了服务平滑发布,下面是其中一个服务的生产环境部署的流水线:
其实平滑发布和平台的关系不大,整体的步骤大概如下:
步骤比较多,并且涉及到大量的shell脚本,这里不把详细的脚本内容列出,简单列出一下每一步的操作(注意某些步骤之间可以插入合理的sleep n保证前一步执行完毕):
代码扫描、单元测试等等。
代码构建,生成构建后的压缩包。
压缩包上传到服务器X中,解压到对应的目录。
向Consul发送指令,把当前发布的X_IP:PORT的负载配置更新为down=1。
stop服务X_IP:PORT。
start服务X_IP:PORT。
检查服务X_IP:PORT的健康状态(可以设定一个时间周期例如120秒内每10秒检查一次),如果启动失败,则直接中断返回,确保还有另一个正常的旧节点参与负载,并且人工介入处理。
向Consul发送指令,把当前发布的X_IP:PORT的负载配置更新为down=0。
上面的流程是通过hard code完成,对于不同的服务器,只需要添加一个发布流程节点并且改动一个IP的占位符即可,不需要对Nginx进行配置重新加载。笔者所在的平台流量不大,目前每个服务部署两个节点就能满足生产需要,试想一下,如果要实现动态扩容,应该怎么构建流水线?
小结服务平滑发布是CI/CD中比较重要的一个环节,而动态负载均衡则是服务平滑发布的基础。虽然现在很多云平台都提供了十分便捷的持续集成工具,但是在使用这些工具和配置流程的时候,最好能够理解背后的基本原理,这样才能在工具不适用的时候或者出现问题的时时候,迅速地作出判断和响应。