Apache + Tomcat - 粘性会话和负载均衡问题

14

我在使用Apache mod_proxy_balancer时遇到了一些关于粘性会话的问题。

我们在Tomcat上开发了一个RESTful Web服务。实际的后端使用Acegi安全框架,并采用基本身份验证。

整个架构如下(很抱歉,我是新用户,无法发布图片):

     --------------------
     |Java Reverse Proxy|
     --------------------
            |
     --------------------
     |Apache load balancer|
     --------------------               
            |
    --------|--------
    |               |
--------        --------    
|tomcat1|       |tomcat2|
--------        --------    
我们有一个"Java反向代理",用于执行各种业务操作。它还在Tomcat(Tomcat1、Tomcat2)上执行基本身份验证。
最终用户调用诸如:http:///a/b?username=foo&password=bar&session=xxx 的URL。
反向代理然后代理请求到Apache,并将凭据作为基本身份验证令牌发送。
最终用户有三个不同的URL:
http://<java reverse proxy domain>/service1
http://<java reverse proxy domain>/service2
http://<java reverse proxy domain>/service3

只有service1和service2受Acegi保护,service3可以匿名访问(这是要求)。

我们在Apache中有以下配置来执行负载平衡:

<Proxy balancer://cluster>
    Header set Cache-Control no-cache
    Header set Pragma no-cache
    BalancerMember http://xxx:9671 route=server1
    BalancerMember http://xxx:9672 route=server2
</Proxy>

ProxyPreserveHost On
ProxyPass / balancer://cluster/ stickysession=JSESSIONID
ProxyPassReverse / balancer://cluster/ stickysession=JSESSIONID

第一次调用service1时,JSESSIONID会返回给用户,然后用户将此会话信息作为请求的一部分发送(在查询字符串中,会话参数)。

为了在后端Tomcats(tomcat1,tomcat2)中维护会话状态,Java反向代理从查询字符串中获取会话并将其作为JSESSIONID cookie发送到代理的Tomcats。

对于受基本身份验证保护的URL,一切都正常。但是当用户调用第三个URL(公开可用)时,Apache无法正确执行负载平衡。

例如,当我调用service1或2时,我会得到以下Apache日志:

[Wed Feb 22 10:48:52 2012] [debug] mod_proxy_balancer.c(280): proxy: BALANCER: Found value "3FB8F8135173BBBE78E5E4BBD6F5C8FB" for stickysession JSESSIONID
[Wed Feb 22 10:48:52 2012] [debug] mod_proxy_balancer.c(1003): proxy: Entering byrequests for BALANCER (balancer://cluster)
[Wed Feb 22 10:48:52 2012] [debug] mod_proxy_balancer.c(1046): proxy: byrequests selected worker "http://xxx:9672" : busy 0 : lbstatus 1
这是完全可以接受的,因为该请求旨在针对tomcat2。但是当我调用service3时,我会得到:
[Wed Feb 22 10:49:27 2012] [debug] mod_proxy_balancer.c(280): proxy: BALANCER: Found value "3FB8F8135173BBBE78E5E4BBD6F5C8FB" for stickysession JSESSIONID
[Wed Feb 22 10:49:27 2012] [debug] mod_proxy_balancer.c(1003): proxy: Entering byrequests for BALANCER (balancer://cluster)
[Wed Feb 22 10:49:27 2012] [debug] mod_proxy_balancer.c(1046): proxy: byrequests selected worker "http://xxx:9671" : busy 0 : lbstatus 0

从这里可以看出,即使JSESSIONID cookie相同,Apache仍将请求发送到错误的tomcat(在此处为tomcat1)。

这可能是因为service3的URL不需要基本身份验证,而service1和service2需要。

我很确定我做错了什么,但我已经找了很长时间,还是无法让它工作。

非常感谢您的帮助。

谢谢

3个回答

6

我看不到你的JSESSIONID上有jvmRoute后缀。mod_proxy使用jvmRoute来正确地将粘性会话路由到Tomcat实例。jvmRoute在您的Tomcat服务器配置中声明(每个服务器实例都具有其自己唯一的jvmRoute标识符)。


没错,在我提供的例子中,我忘记了jvmRoute。但是即使在server.xml中设置它也无法解决问题。 - benjamin.d

1

也许这会有所帮助。这是我在Web服务器上的配置:

<Proxy balancer://hybriscluster>
BalancerMember ajp://tomcatServer1:8009 route=tomcat1 keepalive=On ping=5 max=200 ttl=120
BalancerMember ajp://tomcatServer2:8009 route=tomcat2 keepalive=On ping=5 max=200 ttl=120
ProxySet stickysession=JSESSIONID|jsessionid lbmethod=byrequests timeout=60
</Proxy>

Tomcat服务器1的server.xml配置:

<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1"}">

1

我曾经面临同样的问题,通过修改以下行解决了它 -

ProxyPass /test balancer://mycluster stickysession=JSESSIONID|jsessionid scolonpathdelim=On
<Proxy balancer://mycluster>
BalancerMember http://192.168.1.2:80 route=node1
BalancerMember http://192.168.1.3:80 route=node2
</Proxy>

请注意配置选项 scolonpathdelim=On 参考文献 - http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接