分析nginx upstream权重为0和删除节点

前言:

        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.


大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc