本文介绍了Apache负载平衡tomcat Websocket的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在开发一个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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 14:41