问题描述
我目前正在开发一个websocket应用程序,该应用程序部署在Tomcat服务器上.由于用户数量众多,我想将工作负载分配到多个Tomcat实例.我决定使用Apache进行负载平衡.
I am currently developing a websocket application, which is deployed on a Tomcat server. Because of the huge number of users I would like to distribute the workload to multiple Tomcat instances. I decided to use Apache for load balancing.
现在,我对Apache负载平衡和websockets请求的粘性会话的实现存在问题.这是我的Apache配置:
Now I have a problem with the implementation of Apache load balancing and sticky session for websockets requests. This is my Apache configuration:
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.
The first https request is balanced to Port 8443. The upgraded wss request is also forwarded to 8443.
第二个https请求包含第一个请求的sessionID: https://...& sid = C28C13EEEC525D203F8CA4E827605E0B.jvm1
The second https request contains the sessionID of the first request:https://...&sid=C28C13EEEC525D203F8CA4E827605E0B.jvm1
正如我在Apache日志文件中看到的那样,该sessionID是为stickySession进行评估的:
As I can see in the Apache log file, this sessionID is evaluated for stickySession:
...找到路线jvm1
...Found route jvm1
... balancer://http-localhost:工作者 (htttps://mcsgest1.desy.de:8443/Whiteboard/)重写为 htttps://mcsgest1.desy.de:8443/Whiteboard//?file = octocenter.xml& address =///&& amp; sid = C28C13EEEC525D203F8CA4E827605E0B.jvm1
...balancer://http-localhost: worker (htttps://mcsgest1.desy.de:8443/Whiteboard/) rewritten to htttps://mcsgest1.desy.de:8443/Whiteboard//?file=octocenter.xml&address=///&sid=C28C13EEEC525D203F8CA4E827605E0B.jvm1
第二个https请求仍然在端口8443上,但是升级到websocket协议后,ws-balancer不会评估sessionID并重写为8444:
The second https request is still on port 8443, but after upgrading to websocket protocol, the ws-balancer doesn't evaluate the sessionID and rewrites to 8444:
要在wss协议中同时启用stickysession,我必须在Apache配置中进行哪些更改?我真的需要两个平衡器(http和ws)来平衡websockets吗?
What do I have to change in the Apache config to enable stickysession also for wss protocol? Do I really need two balancers (http and ws) to get websockets balanced?
推荐答案
您不需要单独的websokets平衡器,因为初始的HTTP请求已经具有http cookie并属于正确的实例.
You don't need separate balancer for websokets, because initial http request already has http cookie and belong to right instance.
您只需要检测连接升级并根据Cookie的粘性部分手动路由请求
You just need detect connection upgrade and manually route request depending of sticky part of the cookie
确保为websokets加载代理模块-mod_proxy_wstunnel
Make sure you load proxy module for 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]
这篇关于Apache负载平衡tomcat Websocket的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!