Apache负载平衡tomcat websocket

时间:2016-06-01 09:30:47

标签: apache tomcat websocket load-balancing sticky-session

我目前正在开发一个部署在Tomcat服务器上的websocket应用程序。由于需要大量用户,我希望将工作负载分配给多个Tomcat实例。我决定使用Apache进行负载平衡。

现在我遇到了针对websockets请求的Apache负载平衡和粘性会话的实现问题。这是我的Apache配置:

ProxyRequests off
SSLProxyEngine on
RewriteEngine On

<Proxy balancer://http-localhost/>
    BalancerMember  https://mcsgest1.desy.de:8443/Whiteboard/ route=jvm1 keepalive=On smax=1 connectiontimeout=10 retry=600 timeout=900 ttl=900
    BalancerMember  https://mcsgest1.desy.de:8444/Whiteboard/ route=jvm2 keepalive=On smax=1 connectiontimeout=10 retry=600 timeout=900 ttl=900
    ProxySet lbmethod=byrequests
    ProxySet stickysession=JSESSIONID|sid scolonpathdelim=On
</Proxy>

<Proxy balancer://ws-localhost/>
    BalancerMember  wss://mcsgest1.desy.de:8443/Whiteboard/ route=jvm1 keepalive=On smax=1 connectiontimeout=10 retry=600 timeout=900 ttl=900
    BalancerMember  wss://mcsgest1.desy.de:8444/Whiteboard/ route=jvm2 keepalive=On smax=1 connectiontimeout=10 retry=600 timeout=900 ttl=900
    ProxySet lbmethod=byrequests
    ProxySet stickysession=JSESSIONID|sid scolonpathdelim=On
</Proxy>

RewriteCond       %{HTTP:Upgrade} =websocket
RewriteRule       /jddd/(.*)      balancer://ws-localhost/$1 [P,L]
ProxyPassReverse  /jddd/          balancer://ws-localhost/
RewriteCond       %{HTTP:Upgrade} !=websocket
RewriteRule       /jddd/(.*)      balancer://http-localhost/$1 [P,L]
ProxyPassReverse  /jddd/          balancer://http-localhost/

第一个https请求与端口8443平衡。升级后的wss请求也转发到8443。

第二个https请求包含第一个请求的sessionID: https://...&sid=C28C13EEEC525D203F8CA4E827605E0B.jvm1

正如我在Apache日志文件中看到的,此sessionID是针对stickySession进行评估的:

  

...找到值C28C13EEEC525D203F8CA4E827605E0B.jvm1用于粘性   SID

     

...找到路线jvm1

     

... balancer:// http-localhost:worker   (htttps://mcsgest1.desy.de:8443 / Whiteboard /)重写为   htttps://mcsgest1.desy.de:8443 /白板//文件= octocenter.xml&安培;地址= ///&安培; SID = C28C13EEEC525D203F8CA4E827605E0B.jvm1

第二个https请求仍在端口8443上,但在升级到websocket协议后,ws-balancer不会评估sessionID并重写为8444:

  

... balancer:// ws-localhost:worker   (wss://mcsgest1.desy.de:8444 / Whiteboard /)重写为   WSS://mcsgest1.desy.de:8444 /白板// whiteboardendpoint

我还需要在Apache配置中更改为wss协议启用stickysession吗?我真的需要两个平衡器(http和ws)来平衡websockets吗?

1 个答案:

答案 0 :(得分:2)

您不需要单独的平衡器用于websokets,因为初始http请求已经具有http cookie并且属于正确的实例。

您只需要检测连接升级并根据cookie的粘性部分手动路由请求

确保为websokets加载代理模块 - mod_proxy_wstunnel

例如

SSLProxyEngine on
RewriteEngine On

<Proxy balancer://http-localhost/>
    BalancerMember  https://mcsgest1.desy.de:8443/Whiteboard/ route=jvm1 keepalive=On smax=1 connectiontimeout=10 retry=600 timeout=900 ttl=900
    BalancerMember  https://mcsgest1.desy.de:8444/Whiteboard/ route=jvm2 keepalive=On smax=1 connectiontimeout=10 retry=600 timeout=900 ttl=900
    ProxySet lbmethod=byrequests
    ProxySet stickysession=JSESSIONID|sid scolonpathdelim=On
</Proxy>

RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
RewriteCond %{HTTP_COOKIE} ^.*(JSESSIONID|sid)=([^=]*)\.jvm1 [NC]
RewriteRule .* wss://mcsgest1.desy.de:8443%{REQUEST_URI} [P,L]

RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
RewriteCond %{HTTP_COOKIE} ^.*(JSESSIONID|sid)=([^=]*)\.jvm2 [NC]
RewriteRule .* wss://mcsgest1.desy.de:8444%{REQUEST_URI} [P,L]

RewriteRule  /jddd/(.*)  balancer://http-localhost$1  [P,L]

ProxyPreserveHost On
ProxyRequests Off

ProxyPass /jddd/  balancer://http-localhost
ProxyPassReverse /jddd/ balancer://http-localhost

说明:

# if header upgrade = WebSocket
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]  
# and header connection contains Upgrade (header may be like this: connection=keep-alive, upgrade)
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC] 
# and header cookie contains JSESSIONID or sid, ending with sticky part - .jvm1 in that case
RewriteCond %{HTTP_COOKIE} ^.*(JSESSIONID|sid)=([^=]*)\.jvm1 [NC] 
#than we route request to application server via mod_proxy (P flag) and end rewrite rule check
RewriteRule .* wss://mcsgest1.desy.de:8443%{REQUEST_URI} [P]