Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Introduction

When running on multiple nodes without concurrency control it is possible for the session to become desynchronized during a failover event. Consider the following scenario, where the user (browser) is on Page 1 of an application:

...

Clearly, this scenario presents a problem. Blueriq Runtime addresses this multi-node concurrency problem by using keyspace notifications and interruptible sessions.

Keyspace Notifications

Keyspace notifications are a feature of the key-value store. The key-value store clients (the Runtime nodes in this case) subscribe for notifications for a key or key pattern. The key-value store then notifies its clients when a change occurs for a subscribed key. 

...

OptionUsed ByUsed For
gSpring SessionSpring Session uses this setting, among other things, to detect when an HTTP session is manually deleted.
$BlueriqBlueriq uses this for concurrency control on multiple runtimes.
xSpring SessionSpring Session uses this setting to detect when an HTTP session expires.
KBlueriqBlueriq uses keyspace notifications. That is, it can detect operations on a specific key or set of keys which match a pattern. This is used for concurrency control on multiple runtimes.
ESpring SessionSpring Session uses keyevent notifications. That is, it can detect keys affected by a specific operation.

 

Interruptible Sessions and Flows

Interruptible sessions and flows are a new feature in Blueriq 11. The IAquimaSession and IPortalSession interfaces now extend the Interruptible interface. Each session has an interrupted flag which is not set at the beginning of each request. During the handling of the request, it is possible to interrupt the session, which sets the interrupted flag. The Flow Engine checks the interrupted flag before and after each service call or function call node in the flow. If the session is interrupted, the Flow Engine will not continue the flow and exit with an exception. 

Please note that interrupting the flow does not cause a service call or function call to take the exception exit. Interrupting a session is intended to indicate an abnormal situation in that session instance. All further processing should stop and any state modifications should not be persisted. For this reason, the session manager also checks the interrupted flag and will not save interrupted sessions in the key-value store.

 

Concurrency Control using Keyspace Notifications and Interruptible Sessions

Blueriq Runtime uses keyspace notifications in combination with interruptible sessions in order to prevent a slow Runtime from overwriting the session state. Each request which may modify the session registers with a monitor component within the Runtime. The monitor writes a "guard" key in the key-value store. The guard identifies each session via the session ID and each request through a randomly generated GUID. The monitor also subscribes for keyspace notifications using a key pattern which matches all guards, therefore it is notified when a guard is written. 

...

StepActorDescription
1.User / BrowserThe user clicks a button on Page 1 of the application.
2.Load BalancerThe Load Balancer sends the request to Runtime 1.
3.Runtime 1Before the event handling begins, the session and request are registered with the monitor component. The monitor component generates a GUID to represent the request, registers the session/request pair for the duration of the request and writes a guard key in the key-value store (which is composed from a namespace, session id and the request GUID).
4.RedisRedis notifies Runtime 1 that a guard has been written. Runtime 1 has a single session and request pair registered, and the request GUID of the request matches the request GUID of the guard. Therefore, this does not represent a concurrent modification and no action is taken.
5.RedisRedis notifies Runtime 2 that a guard has been written. Runtime 2 has no session/request pairs registered at this time, so no action is taken.
6.Load BalancerSince Runtime 1 takes too long to respond, the Load Balancer decides to failover to Runtime 2 and resends the request to Runtime 2.
7.Runtime 2Before the event handling begins, the session and request are registered with the monitor component. The monitor component generates a GUID to represent the request, registers the session/request pair for the duration of the request and writes a guard key in the key-value store.
8.RedisRedis notifies Runtime 1 that a guard has been written.
9.RedisRedis notifies Runtime 2 that a guard has been written. The session ID and request GUID from the guard match those of the registered session/request pair, so no action is taken.
10.Runtime 1Runtime 1 has a single session and request pair registered. The session ID from the guard matches the session ID of the registered session/request pair, but the request GUID does not match. This indicates that while the request started at step 2 is still executing, another request was started for the same session (potentially on another node, but it may be the same node as well). The monitor component on Runtime 1 interrupts the registered session. This sets the interrupted flag
11Runtime 1As soon as the Flow Engine exits the current service call or function call node (or as soon as entering one), it detects that the interrupted flag is set and exits with an exception. An error response is sent to the Load Balancer. The Load Balancer does not forward this response back to the user.
12.Runtime 2Runtime 2 finishes handling the event, flows to Page 2 and saves the session state in the key-value store.
13.Runtime 2Runtime 2 sends a success response to the Load Balancer.
14.Load BalancerThe Load Balancer sends the success reponse to the User / Browser.

 

How a request which may modify the session is identified

Any request of type POST, PUT, PATCH or DELETE which is targeted at a controller with a session ID parameter annotated with @AquimaSessionId is considered as a request that can potentially modify the session state. Plugin developers who wish to benefit from concurrency control for their custom controllers should use only POST, PUT, PATCH or DELETE request methods for requests which modify the session state.

How to use concurrency control with other key-value stores

When using a key-value store other than Redis, the IKeyValueStore interface must be implemented and exposed as a Spring managed bean. In order to provide concurrency control an additional interface, IKeyspaceMonitor, must also be implemented and exposed as a Spring managed bean. The concurrency control component within the Runtime will use the provided implementations for IKeyValueStore and IKeyspaceMonitor to register for keyspace notifications and write guards in the key-value store.

Thread Pools and Configuration Options

The default implementation in the Blueriq Redis Key-Value Store Component uses 2 thread pools:

...

  • Subscriptions use a CACHED thread pool. The Runtime subscribes for a key pattern only once, at startup. If the keyspace notifications API is used more often, the thread pool type may be changed to FIXED.
  • Notifications use a FIXED thread pool with 4 threads. Each session modification request causes a guard to be written, which in turn triggers a notification on all Runtime nodes. The amount of work done for each notification is low. Depending on load, the default pool size and type may be adjusted as needed.

 

Panel
Section
Column
width50%

 Previous: 9. Runtime cluster limitations

Column

Next: 11. Session de-synchronization protection