OneConnect? For my iRule?

We get this question often in the iRules v9.x forum:

"I created an iRule that is supposed to choose a host based on the URI (extension, hostname, agent, method, etc), but it doesn't work like I expected. It seems to be logging what I expect to see, and the first request always seems to go to the right place, but then it almost seems to be ignoring my iRule logic. Is there something wrong with my iRule?"

In most cases, there is actually nothing wrong with the iRule.

What's Really Happening?

Here's what's really happening: The HTTP client is opening a Keep-Alive connection and sending multiple requests on the same connection. Since LTM, by default, load balances CONNECTIONS (not REQUESTS), it is treating this connection like any other TCP connection -- directly proxying each client connection to a single server socket, and maintaining this one-to-one relationship between client and server for the life of the client connection.

"But", you say, "my iRule says to choose a new server!"

"But", I say, "the load balancing decision has already been made, and from LTM's perspective that's water under the bridge as long as the server-side connection remains healthy."

"But", you say, "my iRule says to choose a new server!"

Well, there are a couple of ways to make LTM re-consider its load balancing decision mid-connection. One way is to explicitly detach from the existing server before specifying a new one. (Search for "LB::detach" in the iRules v9.x forum for examples, or check out the LB::detach wiki page.) The other is a bit simpler and adds efficiency you couldn't otherwise build into your iRule: Enable OneConnect.

"OneConnect?", you say. "What does that have to do with choosing a new server?"

I know it's not exactly intuitive, but let's look for a minute at how OneConnect works.

How OneConnect Works (condensed version)

OneConnect was originally designed to allow sharing of server-side HTTP keep-alive connections which otherwise would sit idle or time out waiting for that single client to make a new HTTP request (connection pooling) and also to allow distribution of requests matching different criteria to different servers (content switching).

Without OneConnect enabled, the default LTM behaviour is to persist to the first server selected for the life of the connection.

With OneConnect enabled, LTM actively manages each server-side connection to keep it as busy as possible and serve as many requests as possible before requiring a new handshake. Once a response is sent and the server-side connection goes idle, the client-side connection is maintained as usual, waiting for a new request. The connection table entry associating the client to that server is removed, and the server-side connection is kept open and marked available for re-use. This automatic detachment from the server-side flow could be replicated as mentioned above using the LB::detach command.

Since the server-side connection is automatically detached once each response is complete, it can then be shared serially among multiple client requests. When a new request arrives on a client connection, a server-side connection is automatically chosen or established in the appropriate pool (which may or may not be the same server-side connection which handled the last request from that client connection). This automatic re-selection without a new server-side handshake is the secret sauce that you can't otherwise code into an iRule, allowing requests from the same client-side connection to be efficiently served by different servers, transparent to the client.

Enabling OneConnect

There are a couple of iRules commands in the ONECONNECT namespace, but they're not what you need in this case. (More on that in a future article.)

OneConnect is enabled by simply applying a OneConnect profile to the virtual server. You can find them in Local Traffic / Profiles / Other.

OneConnect configured with the default mask of 0.0.0.0 will result in the most efficient connection pooling, allowing any idle server-side connection to be re-used for any new client-side request, significantly reducing the number of server-side connections. However, re-used server-side connections retain the source IP of the original client, which results in some very misleading server log entries unless you also SNAT all connections.

A OneConnect profile with host mask (255.255.255.255) will allow parsing of all requests and server-side connections will only be re-used for the same client. Without SNAT, OneConnect with a host mask (255.255.255.255) keeps the source address info in the server logs consistent with reality.

You can specify any mask that seems appropriate for your traffic, but OneConnect with any mask will be more efficient than no OneConnect at all, since handshake overhead for your servers will be reduced.

Want more?

You can read more about the OneConnect feature and configuration options in the LTM manual on AskF5.

Here's the post where unRuleY made me smarter about OneConnect & re-selection. (Only a little more than a year ago... how long is that in iRule years?) It's an excellent discussion of the details.

And here's another interesting post in which a customer needed to prevent evaluation of all but the first request in a Keep-Alive HTTP connection.

pz
/deb

Published Oct 04, 2007
Version 1.0
  • Would it be possible to get the two functions of OneConnect more prominently discussed in the documentation? (The two being server-side connection aggregation, and causing each of the contained HTTP transactions to be examined.)

     

     

    In particular, I believe that using OneConnect is almost mandatory for most situations involving cookie persistence. It should be documented as such.

     

     

    Two years ago, it took me almost a month to learn from Tech Support that OneConnect would make cookie-persiistence actually work.
  • Does this have the same effect when using HTTP Classes for pool selection based on URI (or any class match)? To paraphrase, are Classes subject to the same connection limitations as iRules?
  • Please clarify the operation of (and virtual necessity of using in certain circumstances such as Cookie persistence) OneConnect in the documentation. We were also stumped by the failure of our HTTP virtual server using Cookie persistence after converting from BigIP 4.6.x to LTM 9.3. We found vague references on-line through random searches that helped us solve the problem while F5 tech support had us try unproductive changes.
  • ckwok's avatar
    ckwok
    Icon for Nimbostratus rankNimbostratus
    If I added a GTM to round robin 2 LTM pools, what happens if request goes to the other LTM with a pool with same members? Does oneconnect persist across LTMs and will hit the same member on the other LTM?