前言:
nginx upstream是大家经常使用的东西,通过upstream方法可以轻易的实现服务的负载均衡。 但往往很多人不理解nginx upstream删除主机跟权重配置为0有什么细节上的区别,从官方的介绍里也只能简单得知,weight = 0 不转发新请求,删除主机用来下线。 但你要明白这类操作对于长连接的影响。因为如果你这个理解不到位,很容易造成服务的异常,哪怕只是一小片时间。 好了,闲话不多说,我们直接通过测试来验证他的结果。
该文章后续仍在不断更新中, 请移步到原文地址 http://xiaorui.cc/?p=5074
权重设为0: upstream把某个节点的权重重置为0,nginx不再往该节点转发新请求,老连接就这么挂着, 已经建立的连接不会中断, 直至超时或主动断开.新连接不会转到节点上来。
移除主机: 在upstream列表中删除该节点,nginx会首先把不在传输中的连接关闭,继而等待数据传输完毕后,把连接关闭掉。
Nginx upstream相关配置
# xiaorui.cc upstream bakend { server 127.0.0.1:7080; server 127.0.0.1:7081; } server { listen 8122 default_server; server_name _; root /var/lib/download; include /etc/nginx/default.d/*.conf; location / { proxy_pass http://bakend; } }
后端服务( 使用golang net/http开发案例)
至于端口变换一下就可以了,另外为了测试活跃的长连接情况,使用chunk分块的方式来延迟返回。
# xiaorui.cc package main import ( "fmt" "io" "net/http" "time" ) func main() { fmt.Println("7080") http.HandleFunc("/test", HandlePost); fmt.Println(http.ListenAndServe(":7080", nil)) } func HandlePost(w http.ResponseWriter, r *http.Request) { w.Header().Set("Connection", "Keep-Alive") w.Header().Set("Transfer-Encoding", "chunked") w.Header().Set("X-Content-Type-Options", "nosniff") ticker := time.NewTicker(time.Second) go func() { for t := range ticker.C { io.WriteString(w, "Chunk\n") fmt.Println("Tick at", t) } }() time.Sleep(time.Second * 15) ticker.Stop() fmt.Println("Finished: should return Content-Length: 0 here") w.Header().Set("Content-Length", "0") }
模拟的客户端
# xiaorui.cc import time import os import requests s = requests.Session() print os.getpid() res = s.get("http://127.0.0.1:8122/test") print res.content time.sleep(10) s = requests.Session() res = s.get("http://127.0.0.1:8122/test") print res.content
总结, 不管是权重配置为0 和 移除主机 都能保证服务的安全的退出,优雅灰度上下线。
END.