Forum Discussion

Don_22992's avatar
Don_22992
Icon for Nimbostratus rankNimbostratus
Oct 06, 2009

Load balancing Java RMI calls

Can the BigIp load balance Java RMI connections?

 

 

BigIp LTM upfront, with JBoss web servers as backend clients. Web clients need to communicate with other applications (on backend servers) via RMI calls which we would like to load balance.

 

 

Web client <-RMI-> Applications client

 

 

How would one set up the virtual server? Is there an article that I can reference?

 

 

-DJ

 

  • Hi DJ,

     

     

    I haven't worked with RMI before, but for generic TCP load balancing with no layer 7 inspection/modification, you can use a Performance Layer4 virtual server which references a FastL4 profile. Define the servers in a pool with a load balancing algorithm like least connections and configure the pool on the virtual server. If you want to persist clients you could add a source address persistence profile.

     

     

    Aaron
  • I don't think it's possible with the default setup of RMI. Because in the first request the server sends back it's own IP to the client, thus ignoring the LB after the first connect.

     

     

    I've heard that you can setup RMI in a different way, but I haven't done it myself...

     

     

    ./J

     

  • It would be much more efficient to change the app configuration to reference the VIP address, but you might also be able to rewrite the response content to replace the server IP with the VIP address using an iRule.

     

     

    Aaron
  • So, can anyone confirm whether it is possible or impossible to load balance RMI using Big IP LTM? If the former, could you provide answers to the following questions:

     

     

    As I understand it, this would require Big IP (iRules) to gain access to the RMI wire protocol internals for retrieving and modifying the server IP sent back (as described above). How is that achieved?

     

     

    Also, to enable server affinity, Big IP (iRules) would need access to a (potentially application-specific) session identifier from the RMI wire protocol to associate the current session with a particular server instance. How is that achieved?

     

     

    Given a location-transparent session fail-over mechanism (such as in GlassFish), I guess fail-over in Big IP would be trivial since any server instance from the pool could be used (i.e. would be the same procedure as load balancing the initial request). Is that a correct assumption?

     

     

    Best regards

     

     

    /Par
  • Hmmm this one looks really tricky. I just had a peek at some RMI overviews and there are several problems that present themselves:

     

     

    1) Depending upon how your architecture is set up, the RMI server may choose a random port. Somehow the client gets to this server and receives the stub.

     

    2) Once a connection to this random port is established, the server initiates another connection for the RMI calls...

     

    3) The objects are almost positively serialized, so getting at the internals would be non trivial.

     

     

    If anyone out there has some deep knowledge of how RMI works I'd love to hear more - this is an interesting use case.

     

     

    -Matt
  • Hamish's avatar
    Hamish
    Icon for Cirrocumulus rankCirrocumulus
    A quick look at an RMI whitepaper I found shows that you can force RMI to happen over port 443 or port 80 if you block the direct communications (It's supposed to be automatic I think...

     

     

     

    Firewalls

     

     

    RMI provides a means for clients behind firewalls to communicate with remote servers. This allows you to use RMI to deploy clients on the Internet, such as in applets available on the World Wide Web. Traversing the client's firewall can slow down communication, so RMI uses the fastest successful technique to connect between client and server. The technique is discovered by the reference for UnicastRemoteObject on the first attempt the client makes to communicate with the server by trying each of three possibilities in turn:

     

     

    * Communicate directly to the server's port using sockets.

     

    * If this fails, build a URL to the server's host and port and use an HTTP POST request on that URL, sending the information to the skeleton as the body of the POST. If successful, the results of the post are the skeleton's response to the stub.

     

    * If this also fails, build a URL to the server's host using port 80, the standard HTTP port, using a CGI script that will forward the posted RMI request to the server.

     

     

    Whichever of these three techniques succeeds first is used for all future communication with the server. If none of these techniques succeeds, the remote method invocation fails.

     

     

    This three-stage back-off allows clients to communicate as efficiently as possible, in most cases using direct socket connections. On systems with no firewall, or with communication inside an enterprise behind a firewall, the client will directly connect to the server using sockets. The secondary communication techniques are significantly slower than direct communication, but their use enables you to write clients that can be used broadly across the Internet and Web.

     

     

     

     

     

    So then it becomes a simpler method of performing load balancing with plain HTTP/HTTPS... (YMMV. I haven't tried this. If the code runs off with your girlfriend it's not my fault).

     

     

    H
  • Update:

     

     

    As of JBoss 4.3, the handling of RMI calls has changed. I would have to ask my developer to explain better, but as I understand it RMI can now listen on 0.0.0.0 and so the IP address of the connection is not as important as the DNS name.

     

     

    I now have an RMI virtual server, connecting to several nodes on port 1099. The initial RMI call, which creates a stub, is load balanced between all active nodes (I am using simple Round Robin). This call returns the stub information, which contains the server name to which the F5 load-balanced the call. Subsequent communication then occurs directly from the origin to this named server. And it all works for us.

     

     

    YMMV, but this is how this turned out here. It did require a new version of JBoss (the initial attempts were made with JBoss 4.0.3)