欢迎访问我的个人博客:kevoo.org
接到这样的需求:把a1系统中的报表中心里的全部报表放到单独的服务器上去运行,其它功能还在以前的服务器。
分析解决:
报表中心里的全部报表都走xxxx/report/xxxx的url,经过讨论,认为可以通过nginx的location元素,实现不同url的请求分发,达到报表与其它业务逻辑分开处理的目的。
所以就兴冲冲的在新服务器部署了a1,然后在nginx服务器上把所有xxx/report/xxx的请求转到新的服务器上了。
可是一测试,问题来了,登录后,点击所有报表,都会跳转到登录页面。问题很明显--用户登录信息丢失了。(因为在页面里,会从session取当前用户信息,如果取不到,会自动跳转到登录页面,让用户登录)
仔细一想,当然会丢失:两个服务器是两个tomcat, session都不一样,登录A服务器后生成的session,肯定是保存在A服务器的内存里的, 执行报表查询时,却要从B服务器取该session,怎么能取到?
看来解决方案也简单了,让两个tomcat实现session共享呗:
从网上下载tomcat共享插件,共5个jar包(javolution-5.4.3.1.jar,memcached-2.4.2.jar,memcached-session-manager-1.3.0.jar,msm-javolution-serializer-cglib-1.3.0.jar,msm-javolution-serializer-jodatime-1.3.0.jar),全部放到tomcat根目录下的lib目录里,然后修改conf/context.xml,在<Context>元素里增加以下内容:
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:111.111.111.11:11211"
requestUriIgnorePattern=".*\.(png|gif|jpg|css|js)$"
sessionBackupAsync="false"
sessionBackupTimeout="100"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"
copyCollectionsForSerialization="false"
/>
之后,重启tomcat,在A与B服务器的tomcat里都做相同的配置即可。
通过telnetmemcache服务器,发现拿着相同的jsessionid可以取到值了,说明配置成功。
再次测试,发现还是之前的问题,所有xxx/report/xxx的链接都会跳转到登录页面。
既然session共享已经实现,为什么还是取不到用户信息?
仔细想想,应该是从两台tomcat里取session信息时,取得key不一样,就是说登录vms后,用户缓存登录信息的key是key1(假设),但跳转到报表页面时,取用户信息用的key不是key1,而是keyother,只有存时用key1,取时用keyother,才会出现取不到值的现象。
于是查看nginx服务器的conf文件,发现在location里的设置里,没有对cookie做专门的设置,就是说,在做请求转发时,没有把cookie信息设置进header头里。于是重新修改了location的配置:
location /a1/report{
proxy_pass http://111.111.111.111:9080;
proxy_set_header Host $host;
proxy_set_header Cookie $http_cookie;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
这样,问题基本得到解决。
运行半天,又出现另一个问题,tomcat下的一个项目,即a2,登录信息依然无效,并且这个项目,还是跑在唯一的一台服务器上,为什么还是取不到session信息呢?
经过代码分析,所有放入memcache里的对像都要实现serializables接口,由于a2放的是user对象,但User类没有实现该接口,所以存入失败导致的。在修改代码,让User类型实现该接口后,问题得到解决。