通过前面一系列的文章介绍,关于CAS的基本知识点大致介绍完了,今天讲解一下CAS中集群的部署。我们知道当访问量越来越来多时,我们需要对CAS服务的性能进行提升,而通过集群的方式提高CAS的服务性能是比较直接的。
在部署的服务中,通过使用nginx来实现负载均衡分发到CAS具体的服务上,但是我们知道前端每次访问时是随机访问分配的,所以就会出现session共享问题,同时在不同CAS中的TGT分配的ticket也不同,因为默认ticket是保存在内存中的。所以我们需要统一管理session和ticket来解决问题。
今天我们来讲解一下CAS的集群部署的使用,在开头我们提到了session和ticket存储管理的方式,在集群下目前使用redis方式,是比较流行和简单的方式,所以今天我们采用这种方式来解决。
在前面的第五章,我们讲解过Service配置不同方式的持久化,这里的session和ticket方式其实也大致类似,我们通过查看官方文档,可以发现官方提供了多种不同Ticket的持久化方式,包括:
JPA
CouchDb
Couchbase
Hazelcast
MongoDb
Redis
…
一系列的操作方式,可以根据自己的需求选择合适的方式即可,这里我们采用Redis配置。
首先引入具体的依赖:
org.apereo.cas
cas-server-support-redis-ticket-registry
${cas.version}
然后在application.properties中添加如下redis的相关配置:
##
# Ticket Registry配置
#
cas.ticket.registry.redis.host=localhost
cas.ticket.registry.redis.database=0
cas.ticket.registry.redis.port=6379
cas.ticket.registry.redis.password=
cas.ticket.registry.redis.timeout=2000
cas.ticket.registry.redis.useSsl=false
cas.ticket.registry.redis.usePool=true
cas.ticket.registry.redis.pool.max-active=20
cas.ticket.registry.redis.pool.maxIdle=8
cas.ticket.registry.redis.pool.minIdle=0
cas.ticket.registry.redis.pool.maxActive=8
cas.ticket.registry.redis.pool.maxWait=-1
cas.ticket.registry.redis.pool.numTestsPerEvictionRun=0
cas.ticket.registry.redis.pool.softMinEvictableIdleTimeMillis=0
cas.ticket.registry.redis.pool.minEvictableIdleTimeMillis=0
cas.ticket.registry.redis.pool.lifo=true
cas.ticket.registry.redis.pool.fairness=false
Redis的地址和密码更改给相应的配置即可,然后我们启动CAS服务。
当我们登录成功后,可以在Redis相应的客户端查看到具体的信息,如下:
同时当我们退出登录后,Redis中的ticket也被销毁掉了。
Session的持久化和Ticket类似,官方同时也为我们提供了多种方式可选。如下:
这里我们选择Redis方式进行配置,同样添加依赖。
org.apereo.cas
cas-server-webapp-session-redis
${cas.version}
同时在application.properties中添加配置项,如下:
##
# Session Redis配置
#
cas.webflow.autoconfigure=true
cas.webflow.alwaysPauseRedirect=false
cas.webflow.refresh=true
cas.webflow.redirectSameState=false
cas.webflow.session.lockTimeout=30
cas.webflow.session.compress=false
cas.webflow.session.maxConversations=5
spring.session.store-type=redis
spring.redis.host=localhost
spring.redis.password=
spring.redis.port=6379
同样的将Redis更改为相应的配置即可。重启服务,可以发现Redis中的Session保存在其中了。
现在我们测试一下集群环境下的CAS是否可用,为了方便测试,我们关闭掉https,在Tomcat中的Server.xml配置了配置http的设置,这里配置了8080和8081端口。
##
# 允许http配置
#
cas.tgc.secure=false
cas.warningCookie.secure=false
重新启动服务,现在我们启动了2个CAS服务来模拟集群情况,分别在8080和8081端口。
通过添加加密配置,如下:
cas.tgc.crypto.enabled=false
注意:使用redis进行session的缓存的时候,起初没有配置这个的时候(当然.signing.key和encryption.key也没有配置)。发现进去无法进行共享session,这是因为cas每次启动的时候会随机生成这两个key的值,这样集群部署的时候就会出现这两个值不一样。当然除了配置false以外,还有一种方式就是将这两个值赋予固定的值。
在Nngix中主要配置upstream参数,默认按照轮询调度的策略选择组内服务器处理请求。
在http模块下配置如下:
upstream cas {
server localhost:8081;
server localhost:8080;
}
然后再在server模块中配置如下:
server {
listen 81;
# server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
proxy_pass http://cas;
}
# .....
}
然后我们启动Nginx服务,访问http://localhost:81/
,然后输入信息进行登陆。发现并不能成功登陆CAS,如果我们更改Nginx中的配置如下:
upstream cas {
server localhost:8081;
server localhost:8080;
ip_hash;
}
重启Nginx发现登录成功!!奇怪了为啥我们统一了session使用Redis管理了,怎么还需要配置ip_hash,那还不如不进行统一管理redis来管理session了。我们知道ip_hash是对每个请求按访问的ip的hash结果分配,这样每次客户端ip固定访问一个后端服务器,可以解决session的问题。
那是因为我们CAS管理session没起作用?我们尝试更换http://localhost:8081
或http://localhost:8080
登录,刷新其他页面http://localhost:81
发现登录成功!然后退出一个CAS服务,其他所以CAS服务都退出了。那说明Redis中的session起作用了,可为啥还是不行?
这个是因为CAS每次登录需要刷新多次才可以登录成功,也就是登录过程发起了多次访问。所以当第一次访问http://localhost:8081
,第二次又跑到http://localhost:8080
,所以在http://localhost:81
登录总是失败。
目前可以通过在upstream中配置jvm_route、sticky或ip_hash来解决,如果你有更好方案,请告知,学习一下。
代码实例:Chapter11