Implementing Durable Client/Server Messaging

Use durable messaging for subscriptions that you need maintained for your clients even when your clients are down or disconnected. You can configure any of your continuous queries or event subscriptions as durable. Events for durable queries and subscriptions are saved in queue when the client is disconnected and played back when the client reconnects. Other queries and subscriptions are removed from the queue.

Use durable messaging for client/server installations that use continuous queries or event subscriptions.

These are the high-level tasks described in this topic:
  1. Configure your client as durable
  2. Decide which subscriptions and continuous queries should be durable and configure accordingly
  3. Program your client to manage durable messaging for disconnect, reconnect, and event handling
See also Durable Event Messaging (GemFire Example).

Configure the Client as Durable

Use one of the following methods:
  • gemfire.properties file:
    durable-client-id=31 
    durable-client-timeout=200 
  • Java:
    Properties props = new Properties(); 
    props.setProperty("durable-client-id", "31"); 
    props.setProperty("durable-client-timeout", "" + 200); 
    DistributedSystem ds = DistributedSystem.connect(props);

The durable-client-id indicates that the client is durable and gives the server an identifier to correlate the client to its durable messages. For a non-durable client, this id is an empty string. The ID can be any number that is unique among the clients attached to servers in the same distributed system.

The durable-client-timeout tells the server how long to wait for client reconnect. When this timeout is reached, the server stops storing to the client's message queue and discards any stored messages. The default is 300 seconds. This is a tuning parameter. If you change it, take into account the normal activity of your application, the average size of your messages, and the level of risk you can handle, both in lost messages and in the servers' capacity to store enqueued messages. Assuming that no messages are being removed from the queue, how long can the server run before the queue reaches the maximum capacity? How many durable clients can the server handle? To assist with tuning, use the GemFire message queue statistics for durable clients through the disconnect and reconnect cycles.

Configure Durable Subscriptions and Continuous Queries

The register interest and query creation methods all have an optional boolean parameter for indicating durability. By default all are non-durable.

// Durable registration
// Define keySpecification, interestResultPolicy, durability 
exampleRegion.registerInterest(keySpecification, interestResultPolicySpecification, true);
                    
// Durable CQ
// Define cqName, queryString, cqAttributes, durability
CqQuery myCq = queryService.newCq(cqName, queryString, cqAttributes, true);

Save only critical messages while the client is disconnected by only indicating durability for critical subscriptions and CQs. When the client is connected to its servers, it receives messages for all keys and queries reqistered. When the client is disconnected, non-durable interest registrations and CQs are discontinued but all messages already in the queue for them remain there.

Note: For a single durable client ID, you must maintain the same durability of your registrations and queries between client runs.

Program the Client to Manage Durable Messaging

Program your durable client to be durable-messaging aware when it disconnects, reconnects, and handles events from the server.
  1. Disconnect with a request to keep your queues active by using Pool.close or ClientCache.close with the boolean keepalive parameter.
    clientCache.close(true);
    Note: To be retained during client down time, durable continuous queries (CQs) must be executing at the time of disconnect.
  2. Program your durable client's reconnection to:
    1. Connect, initialize the client cache, regions, any cache listeners, and create and execute any durable continuous queries.
    2. Run all interest registration calls.
    3. Call ClientCache.readyForEvents so the server will replay stored events. If the ready message is sent earlier, the client may lose events.
    ClientCache clientCache = ClientCacheFactory.create(); 
    // Here, create regions, listeners, and CQs that are not defined in the cache.xml . . .
    // Here, run all register interest calls before doing anything else
    clientCache.readyForEvents(); 
  3. When you program your durable client CacheListener:
    1. Implement the callback methods to behave properly when stored events are replayed. The durable client’s CacheListener must be able to handle having events played after the fact. Generally listeners receive events very close to when they happen, but the durable client may receive events that occurred minutes before and are not relevant to current cache state.
    2. Consider whether to use the CacheListener callback method, afterRegionLive, which is provided specifically for the end of durable event replay. You can use it to perform application-specific operations before resuming normal event handling. If you do not wish to use this callback, and your listener is an instance of CacheListener (instead of a CacheListenerAdapter) implement afterRegionLive as an empty method.