前言:
nginx upstream是大家经常使用的东西,通过upstream方法可以轻易的实现服务的负载均衡。 但往往很多人不理解nginx upstream删除主机跟权重配置为0有什么细节上的区别,从官方的介绍里也只能简单得知,weight = 0 不转发新请求,删除主机用来下线。 但你要明白这类操作对于长连接的影响。因为如果你这个理解不到位,很容易造成服务的异常,哪怕只是一小片时间。 好了,闲话不多说,我们直接通过测试来验证他的结果。
权重设为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.