nginx的upstream模块可以定义后端负载集群,负载的分配方式也有好几种,比如 ip_hash,RR,weight,url_hash,fair等。如果后端集群session不共享的 话,ip_hash,RR,weight,fair等负载均衡方式都将不适用,唯一可用的就是url_hash了。
要用url_hash需要安装第三方模块ngx_http_upstream_hash_module 。安装以及配置方法点击超链接即可。我这里主要介绍如何利用ngx_http_upstream_hash_module对session不共享的集群如何做负载均衡。
upstream的配置如下:
upstream pool1 {
hash $cookie_jsessionid;
server server1:80;
server server2:80;
server server3:80;
hash_again 1;
}
为了保障同一个用户始终分配到同一个后端服务器,我们需要找到能唯一标示用户的标志,毫无疑问,非sessionid莫属了哈哈。因为服务器端也是 根据sessionid区分唯一用户的。所以我们hash用的变量是$cookie_jsessionid 。那么hash_again是什么意思呢?顾名思义hash_again就是再做一次hash的意思,那么什么情况下再做一次hash呢?为什么要再做一 次hash呢?我们配上access_log来看看nginx都做了些什么。
access_log格式配置如下:
log_format main ‘$remote_addr – $remote_user [$time_local] “$request” ‘
‘$status $body_bytes_sent ‘
‘”$http_user_agent” “$http_x_forwarded_for”‘
‘”$upstream_addr” “$upstream_cache_status” “$upstream_status” “$upstream_response_time” “$cookie_jsessionid“‘;
我们主要看upstream_addr、upsteam_status和cookie_jsessionid
首先我们访问下index.jsp,日志如下:
123.127.98.133 – - [02/Jul/2011:19:31:42 +0800] “GET /reg/register.jsp HTTP/1.1″ 200 14540 “Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1″ “-”"server1:80” “-” “200” “0.017″ “-”
此时访问的是server1 sessionid居然为空!其实也可以理解第一次访问时确实木有sessionid,因为sessionid是服务器端生成后写到浏览器的cookie 里的,所以第一次访问肯定没有sessionid了。这样一来,我们可以推测所有用户的第一次请求都是发给同一台后端服务器的。这样的话如果恰好宕机的是 负责处理第一次用户的请求的服务器的话,那么所有的新访问的用户都将无法访问。
F5刷新页面:
123.127.98.133 – - [02/Jul/2011:19:31:46 +0800] “GET http://abc.efg.com/index.jsp” 200 8920 “Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1″ “-”"server2:80” “-” “200” “0.002″ “abcC8pjNRr3jGbAWKNQdt”
有sessionid了,而且请求被重新分配到了server2了,而且之后用户所有的操作都分配到了server2。这个时候我们停掉server2,再次F5刷新页面。日志出如下:
123.127.98.133 – - [02/Jul/2011:19:33:08 +0800] “GET http://abc.efg.com/index.jsp” 200 14540 ” “Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1″ “-”"server2:80, server1:80” “-” “502, 200” “0.002, 0.015″ “abcC8pjNRr3jGbAWKNQdt”
此时虽然我们已经停掉了server2但是我们仍然可以打开页面,为嘛?!此时hash_again大发神威了,此时我们可以从日志里看到 server2返回502,server1返回200。也就是说nginx请求server2是发现,靠!server2挂了,于是基于原来得到的 hash值再次进行hash,从而将请求发往了另外一台机器server1。之后所有的请求也都是这样,先请求server2,server2不可用,重 新hash,访问server1。那么hash_again=2时代表什么了?如果按照我们的配置hash_again=1,那么当server2和 server1都蛋掉,但是server3可用。用户请求时仍然会无法访问。如果我们改成hash_again=2,那么nginx会进行两次hash尝 试,尝试访问后端其他可以用的机器。也就是说hash_again的值越大,整个系统的可用性就越高。