問題
客戶內網系統部署兩個后臺節點,前面使用Nginx做負載均衡。但出現的問題是, 一臺服務器承擔了幾乎所有流量,而另一臺服務器基本上沒有任何流量。
分析
問題出在Nginx的負載均衡策略上面。配置的兩個節點負載均衡,采用的是ip_hash策略,即基于客戶端IP地址來確定訪問哪個服務節點的策略。算法是根據請求所屬客戶端IP計算得到一個數值,然后把請求發往該數值對應的后端。所以同一個客戶端的請求,都會發往同一個后臺服務節點。除非該節點不可用了。Ip_hash策略的優點是能夠保持會話。
那么這個策略有什么問題呢?這個問題出在Nginx對Ip_hash的算法上。這段算法的核心部分如下:
for (i = 0; i < 3; i++) {
// iphp->addr[i]為ip的點分十進制法的第i段
hash = (hash * 113 + iphp->addr[i]) % 6271;
}
通過客戶端ip計算得到一個值。但是問題就出在這段算法上,可以看到,這段算法循環了三次,而正常的IP地址有四個部分,這里只是將IP的前三個部分作為參數加入hash函數。因此,如果前三部分是一樣的話,那么意味著他們都會被分配到同一臺服務器上。
那么為什么Nginx要這樣設計呢?因為IP地址前三位相同一般意味著來自同一個局域網或者相領區域,使用相同的后端服務能夠讓Nginx在一定程度上更具有一致性。
所以因為客戶的內網用戶端多在同一個網段,所以最終的結果就是在同一個網段的請求都被Nginx分發到了一個節點上,導致了兩個節點的流量不均衡。