解决问题
CAS登录过程会有三次请求,我们依次命名为Authentication Request / Validation Request / Wrapper Request。Nginx缺省的分发规则,同一个浏览器的请求,会按照nginx自身某种规则进行分发。在双点集群环境下,Authentication Request和ValidationRequest可能会恰好被分发到两台服务器,这就会导致登录过程死循环,导致在集群下,点击登录后会在登录页面刷新多次。
工作原理
Sticky是nginx的一个模块,它是基于cookie的一种nginx的负载均衡解决方案,通过分发和识别cookie,来使同一个客户端的请求落在同一台服务器上,默认标识名为route
1.客户端首次发起访问请求,nginx接收后,发现请求头没有cookie,则以轮询方式将请求分发给后端服务器。
2.后端服务器处理完请求,将响应数据返回给nginx。
3.此时nginx生成带route的cookie,返回给客户端。route的值与后端服务器对应,可能是明文,也可能是md5、sha1等Hash值
4.客户端接收请求,并保存带route的cookie。
5.当客户端下一次发送请求时,会带上route,nginx根据接收到的cookie中的route值,转发给对应的后端服务器。
安装
Sticky模块下载地址:
解压后放在/root/cluster/nginx-sticky目录下
解压后放在目录/root/cluster/nginx-1.14.0目录下
编译安装nginx,加入sticky模块
[root@localhost ~]#cd cluster/nginx-1.14.0
[root@localhost nginx-1.14.0]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module --add-module=/root/cluster/nginx-sticky
[root@localhost nginx-1.14.0]# make
[root@localhost nginx-1.14.0]# make install
安装完查看nginx编译参数
[root@localhost nginx-1.14.0]# /usr/local/nginx/sbin/nginx -V
如果出现以下内容说明安装成功
nginx version: nginx/1.14.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC)
configure arguments: --prefix=/root/cluster/nginx --with-http_gzip_static_module --with-http_flv_module --with-http_dav_module --with-http_stub_status_module --with-http_realip_module --add-module=/root/cluster/nginx-sticky/
然后修改nginx的conf配置,修改文件usr/local/nginx/conf/nginx.conf
如果在以上编译过程中报错,提示找不到MD5等问题,可能的问题如下
ngx_http_sticky_misc.c: In function 「ngx_http_sticky_misc_md5」:
ngx_http_sticky_misc.c:152:15: ERROR:「MD5_DIGEST_LENGTH」 undeclared (first use in this function)
u_char hash[MD5_DIGEST_LENGTH];
解决方式就是修改你下载解压缩之后的sticky模块文件夹中的ngx_http_sticky_misc.c文件,将这两个模块 and 包含到文件ngx_http_sticky_misc.c
添加下面红色标注的代码
#include
#include
#include
#include
#include
#include
#include
#include
#include "ngx_http_sticky_misc.h"
然后重新再编译一次。
在upstream加入sticky配置,配置如下,nginx负载均衡配置参考文章《Nginx+Tomcat搭建高性能负载均衡集群》
upstream 192.168.203.176 {
sticky;
server 192.168.203.31:8090;
server 192.168.203.32:8090;
server 192.168.203.33:8090;
}
加入sticky;后,重启nginx就可以了。
sticky参数解析
sticky [name=route] [domain=.foo.bar] [path=/] [expires=1h]
[hash=index|md5|sha1] [no_fallback] [secure] [httponly];
[name=route] 设置用来记录会话的cookie名称
[domain=.foo.bar] 设置cookie作用的域名
[path=/] 设置cookie作用的URL路径,默认根目录
[expires=1h] 设置cookie的生存期,默认不设置,浏览器关闭即失效,需要是大于1秒的值
[hash=index|md5|sha1] 设置cookie中服务器的标识是用明文还是使用md5值,默认使用md5
[no_fallback] 设置该项,当sticky的后端机器挂了以后,nginx返回502 (Bad Gateway or Proxy Error) ,而不转发到其他服务器,不建议设置
[secure] 设置启用安全的cookie,需要HTTPS支持
[httponly] 允许cookie不通过JS泄漏
注意
1.同一客户端的请求,有可能落在不同的后端服务器上
如果客户端启动时同时发起多个请求。由于这些请求都没带cookie,所以服务器会随机选择后端服务器,返回不同的cookie。当这些请求中的最后一个请求返回时,客户端的cookie才会稳定下来,值以最后返回的cookie为准。
2.cookie不一定生效
由于cookie最初由服务器端下发,如果客户端禁用cookie,则cookie不会生效。
3.cookie名称不要和业务使用的cookie重名。Sticky默认的cookie名称是route,可以改成任何值。
4.客户端发的第一个请求是不带cookie的。服务器下发的cookie,在客户端下一次请求时才能生效。
5.Nginx sticky模块不能与ip_hash同时使用