因业务需要,想给 OFBiz 配置一下集群,看了一下相关资料,大概想了2中方案:
一种是使用 Tomcat 自带的 Cluster 配置中的 session 同步,另外一种是使用开源软件来进行 Redis 的 session 同步
分别对这2中方案,进行了配置,着重写一个第二种方案,有坑!在最后。
环境:MacOS Sierra,OFBiz 12.04
1、Tomcat 插件中使用了 tomcat-cluster-redis-session-manager (https://github.com/ran-jit/tomcat-cluster-redis-session-manager) ,下载插件中的所有包,其中第一个包可以不要,第四个包可以替换成源代码,方便的 Debug 和学习,复制到OFBIZ_HOME/framework/catalina/lib 目录下
2、修改 org.ofbiz.catalina.container.CatalinaContainer 类中,configureContext方法,增加如下代码
(由于 OFbiz 采用的是嵌入式 Tomcat(不知道这种叫法对不对,总之是通过代码来启动 Tomcat,类似 SpringBoot),这里就直接记录,用 Tomcat 配置文件的,可以看 https://my.oschina.net/hollowj/blog/793489 ,我就是参考的这边文章。)
增加一个 Valve,然后替换原来的 Manager
try {
Valve v = ((Valve)Class.forName("tomcat.request.session.redis.SessionHandlerValve").newInstance() );
context.addValve(v);
Manager m = (Manager)Class.forName("tomcat.request.session.redis.SessionManager").newInstance();
context.setManager(m);
Debug.log("====================");
Debug.log(v.toString());
Debug.log("====================");
Debug.log(m.toString());
Debug.log("====================");
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
3、增加配置文件 redis-data-cache.properties 在 /framework/catalina/config/redis-data-cache.properties 中
redis.hosts=127.0.0.1:6379 #redis 地址,每个服务器都应该一样
redis.cluster.enabled=false #是否启用 redis 集群,默认关闭
redis.database=0 #默认 redis 数据库
4、然后运行2个 OFBiz 实例,分别启动
5、配置 Nginx 负载均衡(略),网上一大堆,附上我的配置
upstream upstream80 {
server 127.0.0.1:8080;
server 192.168.15.201:8080;
}
server {
listen 8888;
server_name localhost;
location / {
proxy_pass http://upstream80;
proxy_set_header Host $host:$server_port;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
proxy_connect_timeout 600s;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
6、启动 Nginx 和2个 OFBiz,写了一个小的 servlet 测试一下
http://localhost:8888/zuczugwarehouse/control/testSessionEvent?partyId=10014 地址地址是设置一个 partyId 到 session 中
http://localhost:8888/zuczugwarehouse/control/testSessionEvent? 这个地址是从 session 中读取一个 partyId
一种测试方法是,先启动一台机器,然后带参数设置 Session,接着启动另一台机器,访问不带参数的地址,看看2台机器是否都能获取到 session 中的 partyId
下图是只启动了 A 实例,设置了一个 attribute 到 session 中
接着启动 B 实例,使用不带参数的连接,看看每次访问是不是都能读取到 session 中的 attribute,可以看到,不到参数的连接分别从2个实例中都获取到了 attribute
到此为止,OFBiz 配置集群的 session 同步问题,就已经搞定了,然后在测试的过程中,发现了1个小坑,就是 session 中设置的 attribute,如果不手动remove,会影响到 ftl 或者是 service 中的参数影响。
首先,screen 中的通用参数上下文,是通过下面的方法创建的,如果一旦放到 session 之后,参数如何怎么传 新值,始终会被 session 里的 attribute的旧值覆盖
service 同理,ServiceEventHandler 在处理参数的时候,如果没有传入参数的话,就用用 session 的 attribute 覆盖
解决办法是,session 除了用过状态验证之外不要放其他东西,如果一定要放,尽量取一些比较独特的名字