參考:http://www.54xue.com/w/25/n-15025.html
nginx的upstream目前支持4種方式的分配
1、輪詢(默認)
每個請求按時間順序逐一分配到不同的後端服務器,如果後端服務器down掉,能自動剔除。
2、weight
指定輪詢機率,weight和訪問比率成正比,用於後端服務器性能不均的情況。
2、ip_hash
每個請求按訪問ip的hash結果分配,這樣每個訪客固定訪問一個後端服務器,可以解決session的問題。
3、fair(第三方)
按後端服務器的響應時間來分配請求,響應時間短的優先分配。
4、url_hash(第三方)
按訪問url的hash結果來分配請求,使每個url定向到同一個後端服務器,後端服務器爲緩存時比較有效。
負載均衡:
只需要在http中增加
upstream tgcluster {#定義負載均衡設備的Ip及設備狀態
ip_hash;
server 127.0.0.1:9090
down;
server 127.0.0.1:8080 weight=2;
server 127.0.0.1:6060;
server 127.0.0.1:7070 backup;
}
在需要使用負載均衡的server中增加
proxy_passhttp://tgcluster/;
每個設備的狀態設置爲:
1.down 表示單前的server暫時不參與負載
2.weight 默認爲1.weight越大,負載的權重就越大。
3.max_fails :允許請求失敗的次數默認爲1.當超過最大次數時,返回proxy_next_upstream 模塊定義的錯誤
4.fail_timeout:max_fails次失敗後,暫停的時間。
5.backup: 其它所有的非backup機器down或者忙的時候,請求backup機器。所以這臺機器壓力會最輕。
http://www.blogjava.net/tunaic/archive/2009/11/30/304212.html
nginx使用ip_hash做負載均衡的問題及解決辦法
原文地址:http://bbs.sudone.com/thread-145-1-1.htmlsquid<=>nginx<=>server(s)
前端使用squid做緩存,後端用多臺服務器,但多臺服務器間的SESSION不共享,爲了做負載均衡,使用nginx的ip_hash來做,使得來源機器的會話是持續的。
於是便引起來了一個問題,使用nginx的ip_hash規則來做負載均衡時,得到的IP則始終是squid機器的IP,於是負載均衡便失效了。
同理,在使用nginx的ip_hash做負載均衡方案時也會存在這個問題,即realip的問題,nginx有一個realip的模塊,但並沒有解決 ip_hash的realip的問題,因此當通過代理訪問你的網站就會引起分佈均的問題,這種情況在小範圍的負載方案中會表現的尤爲突出。
nginx中有一個ngx_http_request_t的數據結構,其中的x_forwarded_for存儲的就是realip的信息(當然這是存在安全問題的).
- typedef struct {
- ngx_uint_t hash;
- ngx_str_t key;
- ngx_str_t value;
- u_char *lowcase_key;
- } ngx_table_elt_t;
於是便實現了ip_hash使用realip來做負載均衡的方案:
爲ngx_http_upstream_ip_hash_module.c這個文件添加一個函數用來獲取realip.
- static ngx_int_t ngx_http_upstream_realip(ngx_http_request_t *r);
- static ngx_int_t
- ngx_http_upstream_realip(ngx_http_request_t *r)
- {
- u_char *ip,
*p;
- size_t len;
- in_addr_t addr;
- struct sockaddr_in *sin;
- if (r->headers_in.x_forwarded_for == NULL) {
- return
NGX_DECLINED;
- }
- len = r->headers_in.x_forwarded_for->value.len;
- ip = r->headers_in.x_forwarded_for->value.data;
- for (p = ip + len - 1; p > ip; p--) {
- if
(*p == ' ' || *p == ',') {
- p++;
- len
-= p - ip;
- ip
= p;
- break;
- }
- }
-
-
- sin = (struct sockaddr_in *) r->connection->sockaddr;
- addr
= inet_addr((char *) ip);
- if (addr == INADDR_NONE) {
- return
NGX_DECLINED;
- }
- p
= ngx_palloc(r->connection->pool, len);
- if
(p == NULL) {
- return
NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
- ngx_memcpy(p,
ip, len);
- sin->sin_addr.s_addr
= addr;
- r->connection->addr_text.len
= len;
- r->connection->addr_text.data
= p;
- return NGX_DECLINED;
- }
- ngx_http_upstream_realip(r);