文章目录
一、会话保持
会话保持,有时又可叫做 粘滞会话(Sticky Sessions)
。
- 会话保持是指:在负载均衡器上的一种机制,可以识别客户端与服务器之间交互过程的关连性,在作负载均衡的同时还保证一系列相关连的访问请求都会分配到一台机器上。 通俗讲就是,在一次会话过程中发起的多个请求都会落到同一台机器上。
1.1 会话(session)与连接(connection)之间的区别
连接: 我们都知道TCP/IP协议中经常提到的:”三次握手,四次挥手“的问题。自然也知道客户端和服务器端是经过三次握手以后,建立了连接(connection)
。当它们建立了连接以后,那么客户端就可以向服务端发送多次的请求。如果客户端和服务器端需要断开连接,那么就需要经过四次的挥手过程才能够断开连接。
会话: 如果用户需要登录,那么可以理解为经过三次握手以后,客户端与服务器端建立的就是会话(session)
。如果用户不需要登录,那么可以理解为经过三次握手以后,客户端与服务器端建立的就是连接(connection).
从简单的角度来看,如果用户需要登录,那么就可以简单的理解为会话;如果不需要登录,那么就是连接。
1.2 为什么要会话保持?
实际上,会话保持机制
与负载均衡的基本功能
是完全矛盾的。
负载均衡
希望将来自客户端的连接、请求均衡的转发至后端的多台服务器,以避免单台服务器负载过高;会话保持机制
却要求将某些请求转发至同一台服务器进行处理。
原始负载均衡的基本原理:
- 对于同一个连接中的数据包,负载均衡会将其进行NAT转换后,转发至后端固定的服务器进行处理,这是负载均衡最基本、最原始的功能。负载均衡系统内部会专门有一张表来记录这些连接的状况,包括:
[源IP:端口]、[目的IP:端口]、[服务器IP:端口]、空闲超时时间(Idle Timeout)等等
。
由于这张表需要消耗系统的内存资源,因此,这张表不可能无限大,所有厂家都会有一定的限制。这张表的大小一般称之为最大并发连接数,也就是系统同时能够容纳的连接数量。考虑到建立连接的客户端或服务器会发生异常状况,导致连接不能被正常终结掉,因此,负载均衡的当前连接状态表项中有一个空闲超时时间的参数。如果在规定的时间内某个连接不再有请求,那么这个连接就会被清除掉,释放系统资源。那么,删除连接以后,客户端的请求将无法继续发往同一个后端的服务器,那么就会导致数据丢失等等。
常见的异常场景包括:
- 客户端输入了正确的用户名和密码,但却反复跳到登录页面;
- 客户端放入购物篮的物品丢失;
- 用户输入了正确的验证码,但是总提示验证码错误
因此,会话保持机制的意义就在于,确保将来自相同客户端的请求,转发至后端相同的服务器进行处理。如果在客户端和服务器之间部署了负载均衡设备,很有可能,这多个连接会被转发至不同的服务器进行处理。如果服务器之间没有会话信息的同步机制,会导致其他服务器无法识别用户身份,造成用户在和应用系统发生交互时出现异常。
1.3 会话保持在Nginx中的实现
1、ip_hash机制
- ip_hash技术能够将 某个ip 的请求定向到同一台后端web机器中, 这样一来这个ip 下的客户端和某个后端web机器就能建立起稳固的session.
- ip_hash技术能够让某一客户机在相当长的一段时间内只访问固定的后端的某台真实的web服务器,这样会话就会得以保持,在网站页面进行login的时候就不会在后面的web服务器之间跳来跳去了,也不会出现登录一次的网站又提醒重新登录的情况.
缺陷:
- nginx不是最前端的服务器:当多个客户是通过 代理或地址转换 的方式来访问服务器时,由于都分配到同一台服务器上,会导致服务器之间的负载严重失衡。例如,使用的是squid反代为最前端.那么nginx取ip时只能得到squid的服务器ip地址,用这个地址来作分流肯定是不对的。
- nginx的后端还有其它负载均衡:若nginx后端还有其它负载均衡,将请求又通过另外的方式分流了。
2、nginx-sticky-module这个第三方模块
Sticky
是基于cookie
的一种负载均衡解决方案,通过分发和识别cookie,使来自同一个客户端的请求落在同一台服务器上,换一种说法,服务器给客户端下发一个cookie,具有特定cookie的请求会分配给它的发行者,默认cookie标识名为route
。
工作原理
- 客户端首次发起访问请求,nginx接收后,发现请求头没有cookie,则以轮询方式将请求分发给后端服务器。
- 后端服务器处理完请求,将响应数据返回给nginx。
- 此时nginx生成带route的cookie,返回给客户端。route的值与后端服务器对应,可能是明文,也可能是md5、sha1等Hash值
- 客户端接收请求,并保存带route的cookie。
- 当客户端下一次发送请求时,会带上route,nginx根据接收到的cookie中的route值,转发给对应的后端服务器。
什么是cookie
HTTP协议本身是无状态的。什么是无状态呢,即服务器无法判断用户身份。Cookie实际上是一小段的文本信息(key-value格式)。客户端向服务器发起请求,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。
打个比方,我们去银行办理储蓄业务,第一次给你办了张银行卡,里面存放了身份证、密码、手机等个人信息。当你下次再来这个银行时,银行机器能识别你的卡,从而能够直接办理业务。
二、实现会话保持具体过程
在上一篇博客中,我们已经实现了负载均衡,但是遗留问题:新的数据覆盖旧的数据内容,造成数据的丢失,现在我们就来解决它。
实验环境
主机(版本:ip) | 功用 |
---|---|
虚拟机server1(rhel6.5:172.25.2.1) | lnmp环境主机+tomcat1服务器 |
虚拟机server2(rhel6.5:172.25.2.2) | tomcat2服务器 |
真机(rhel7.3:172.25.2.250) | 测试机 |
1、在nginx-1.14中不支持nginx-sticky-module
模块,所以使用nginx-1.10版本,重新编译nginx
tar zxf nginx-1.10.1.tar.gz
tar zxf nginx-sticky-module-ng.tar.gz -C /usr/local/
2、注释掉debug日志,不显示nginx的版本号,把openresty的nginx关掉,否则会占用80端口,导致服务器起不来
/usr/local/openresty/nginx/sbin/nginx -s stop
3、重新编译,加入sticky模块,然后安装:
./configure --prefix=/usr/local/lnmp/nginx \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-threads --with-file-aio \
--user=nginx --group=nginx \
--add-module=/mnt/nginx-sticky-module-ng
make && make install
编译完,我们可以查看是否加入了nginx-sticky-module
安装
4、编辑nginx配置文件,其实复制之前的openresty下的nginx配置文件,修改即可。
[root@server1 nginx-1.10.1]# cp /usr/local/openresty/nginx/conf/nginx.conf /usr/local/lnmp/nginx/conf/
[root@server1 nginx-1.10.1]# vim /usr/local/lnmp/nginx/conf/nginx.conf
17 http {
18 upstream tomcat{
19 sticky;
20 server 172.25.2.1:8080;
21 server 172.25.2.2:8080;
22 }
不用的代码可以注释掉。
5、创建软链接,并启动nginx。
[root@server1 nginx-1.10.1]# ln -s /usr/local/lnmp/nginx/sbin/nginx /sbin/
[root@server1 nginx-1.10.1]# nginx
[root@server1 nginx-1.10.1]# netstat -tnlp
6、先清除缓存,访问测试页http://172.25.2.1/test.jsp
我们添加数据,发现数据不丢失,而且id号不改变,到此我们实现了会话保持。
7、此时,我们关闭tomcat1
,再次访问测试页面,却发现server1
上面的数据没有同步到server2
上
[root@server1 bin]# pwd
/usr/local/tomcat/bin
[root@server1 bin]# ./shutdown.sh
我们可以看出,客户会一直访问同一台tomcat服务器,实现了会话保持,即使后台一台tomcat服务器宕机,切换到另外一台tomcat服务器上面依然可以实现会话保持,但是此时在第一个tomcat主机上面的数据丢失。
在下一篇博客中,我们解决此问题。