Load Balance WebSockets using Apache HTTPD (Tech Tip #48)

JBoss EAP 6.3 provides a technology preview of WebSocket and WildFly have supported them as part of Java EE 7 compliance.

github.com/javaee-samples/javaee7-samples/tree/master/websocket provide tons of Java EE 7 samples that run on WildFly. If you are interested in similar functionality on JBoss EAP 6.3 then github.com/jboss-developer/jboss-eap-quickstarts/tree/6.4.x-develop/websocket-hello is a quickstart. In addition, there are a few more samples at github.com/arun-gupta/jboss-samples/tree/master/eap63.

One of the common questions asked related to WebSockets is how to how to load balance  them. This Tech Tip will explain that for WildFly and JBoss EAP 6.3.

First, what are the main components ?

  • At least Apache HTTPD 2.4.5 is required. Now HTTPD binaries are not available for Mac but fortunately compiling instructions are explained clearly in Tech Tip #45.
  • mod_proxy_wstunnel is an Apache module that provides support for tunneling of Web Socket connections to a backend Web Sockets server, such as WildFly or JBoss EAP. It is a support module to mod_proxy that provide support for a number of popular protocols as well as several different load balancing algorithms. The connection is automagically upgraded to a WebSocket connection.  And all the modules are already included in the modules directory.
  • mod_proxy_balancer module is required that provides load balancing for HTTP and other protocols.

Let’s go!

  1. Download and unzip WildFly 8.1.
  2. Start WildFly 8.1 in domain mode using ./bin/domain.sh.
  3. Download this chat sample, rename the file to “chat.war” and deploy to “main-server-group” as:
    The only difference from the original Java EE 7 WebSocket Chat sample is the addition of System.getProperty("jboss.node.name") to display the name of WildFly instance serving the application. The source code is available at github.com/arun-gupta/wildfly-samples/tree/master/websocket-loadbalance.
  4. Uncomment the following lines in /usr/local/apache2/conf/httpd.conf:
    This will enable all the required modules.
  5. Add the following code fragment at the end of “httpd.conf”:
    Proxy is a container for proxied resources and is creating a load balancing group in this case using balancer directive. BalancerMember adds a member to this load balancing group.  ProxyPass is a standard directive that maps remote servers running on different ports into the space of the local server. In this case, WildFly is started in domain mode and so starts two instances on port 8080 and 8230. Both of these instances are mapped to localhost:80, which is where Apache HTTPD is running by default.

The deployed chat sample is now accessible at localhost:8080/chat (first instance in the managed domain), localhost:8230/chat (second WildFly instance in the managed domain), and localhost/chat (via Apache HTTPD).

Now even if you kill one of the WildFly instances, the other instance will continue to serve the client. Note, this only gives application availability as there is no session failover in this.

This was also verified on JBoss EAP 6.3 and there are a few differences:

  1. Use the sample from github.com/arun-gupta/jboss-samples/tree/master/eap63/websocket-chat instead.
  2. The generated archive name is different and so the command would look slightly different too:
  3. Configure “httpd.conf” as:

And that’s it!

Watch this live in action:

An important point to understand is that there is no concept of “sticky sessions” in WebSocket as, unlike HTTP, there is a direct and “permanent” connection between the client and the server in this case.

Enjoy!

Be Sociable, Share!
  • Tweet

16 thoughts on “Load Balance WebSockets using Apache HTTPD (Tech Tip #48)

  1. Great tip, for WildFly.

    Unfortunately, httpd 2.4 is not a supported web server for EAP 6 (see https://access.redhat.com/articles/111663). And mod_proxy isn’t a supported connector.

    Is there an integration with mod_cluster ?

  2. Thanks so much for posting this! I’ve been struggling with this very issue for the last couple of months. Glad to see someone was looking into it!

  3. Apache 2.4 is now being shipped on RHEL as part of the new Software Collections channels. It includes mod_proxy_wstunnel and a number of our users are looking at it as a solution.

    JBoss will ship Apache 2.4 with mod_proxy_wstunnel, but likely not until 2015.

  4. At the end of the video, you promised a blog about how to implement http session failover. Is this still on your radar? :)

  5. Great post, can you offer any advice regarding session replication over multiple hosts? Using your web app as provided I can see that session data is being shared by nodes on the same host as expected. However when a second host is added to the server group when the session is passed to the second host session data is not synced. Thanks again for this great resource.

  6. Your solution means that browser does always support websockets…
    But in real life users can use browsers not supporting websockets, e.g. IE9.
    Can you help with the apache balancer configuration which will work at the same time for browsers supporting and not supporting websockets?
    In such case to avoid errors there should not be force upgrading to websockets if browser does not support it.

  7. I created my wildfly cluster following the document https://docs.jboss.org/author/display/WFLY8/WildFly+8+Cluster+Howto

    As per the document I commented out mod_proxy_balancer.so from my httpd.conf

    Can I achieve this the websocket load balancing with with mod_proxy_cluster.so instead of mod_proxy_balancer.so

  8. Natalaya,
    For browsers that do not support websockets natively, you can have SockJs support on the server side for fallback to XHR/XDR streaming or polling. Refer to https://github.com/sockjs/sockjs-client

    Alternatively, what we do currently is use a flash websocket bridge for browsers that do not natively support Websockets.
    Refer to https://github.com/gimite/web-socket-js

  9. Thanks a lot! :)
    In my case I had to add this additional module

    LoadModule slotmem_shm_module modules/mod_slotmem_shm.so

  10. Hi, author

    I set my httpd.conf like below as you mentioned in you blog.

    # Define back-end servers:

    # Server 1
    BalancerMember ws://10.214.49.65:8080/

    # Server 2
    BalancerMember ws://10.214.49.83:8080/

    ProxyPass /ademo balancer://mycluster/ademo
    ProxyPassReverse /ademo balancer://mycluster/ademo

    But when I tried to visit my apache httpd using http://xxxxxxx/ademo/socket.html.
    It failed, Internal Server Error, and I can find below logs in error_log of httpd.
    [Fri Jan 08 02:55:50.840362 2016] [proxy:warn] [pid 18446:tid 46971298007360] [client 10.248.66.148:52033] AH01144: No protocol handler was valid for the URL /ademo/socket.html. If you are using a DSO version of mod_proxy, make sure the proxy submodules are included in the configuration using LoadModule.

    But I can directly visit my backend server tomcat successfully.
    I need to mention that I have applied the neccessary modules so files in httpd.conf including modules/mod_proxy_wstunnel.so.

  11. Hi Arun,

    Just for the clarification. It might be obvious to people who have experience with websocket protocol but did you mean:

    “there is a direct and “permanent” connection between the client and the application server in this case”

    by

    “there is a direct and “permanent” connection between the client and the server in this case”

Leave a Reply

Your email address will not be published. Required fields are marked *