Session Consistency and the .NET Client SDK - azure-cosmosdb

I am trying to understand what Sessions Consistency actually means when working with Azure DocumentDb via the .NET client SDK i.e. What defines (and bounds) a session. Is a new session created each time we create a new instance of DocumentClient and if so does the behavior change if we are using the IReliableReadWriteDocumentClient wrapper?

Yes, a new session is created each time you create a new instance of the DocumentClient class. Each DocumentClient instance maintains a map of collection -> session token mapping. The client saves the latest session token received from the server, and echoes it as a header (x-ms-sessiontoken) during read requests. This enables DocumentDB to locate an up-to-date replica of your collection to serve session (or read-your-writes) consistency. This is the same with IReliableReadWriteDocumentClient, since it's a wrapper over the DocumentClient.
Note: the easiest way to achieve session consistency is to have a single DocumentClient instance manage it for you automatically. You can also manage a logical session across multiple DocumentClient instances with a little more complexity. For example, let's say that you have a load balanced Web API with two servers each with a DocumentClient instance, and you want session consistency across these servers.
client writes -> App Server 1 -> DocumentDB
client reads -> App Server 2 -> DocumentDB
You can implement this by saving the x-ms-sessiontoken returned in step 1 by saving it as a cookie in the client, then echoing that x-ms-sessiontoken in the read request. By round-tripping the session token, you can get session consistency.

Related

When is the right time to create dynamodb connection in a server application?

Let's assume you are developing a server-side application with express and for incoming requests, you have to access DynamoDb and retrieve something. The question is, when is the right time to instantiate the DynamoDb connection:
const dynamodb = new AWS.DynamoDB({
region: process.env.AWS_DEFAULT_REGION,
});
const docClient = new AWS.DynamoDB.DocumentClient({ service: dynamodb });
Should I do this once for all the API handlers or should I create a new connection for each incoming request?
As a best practice, it is recommended to declare DocumentClient the outside the function. However, please note that DocumentClient is not a database connection object. DocumentClient is just an abstraction in the AWS.DynamoDB namespace. The document client abstraction makes it easier to read and write data to Amazon DynamoDB with the AWS SDK for JavaScript.
Unlike RDBMS connection, it is not required to maintain the connection or connection pool to connect to DynamoDB database.
DynamoDB is a web service, and interactions with it are stateless.
Applications do not need to maintain persistent network connections.
Instead, interaction with DynamoDB occurs using HTTP(S) requests and
responses.
new AWS.DynamoDB(options = {}) ⇒ Object
The service object AWS.DynamoDB uses asynchronous request to send data to DynamoDB. The DocumentClient also uses this service object internally.
By default, the SDK will send asynchronous HTTP requests to DynamoDB. However, you can change the default behavior by setting the attribute httpOptions.xhrAsync to false.

Session state access in Web API across domains

I have a ASP.Net API implementation, where to store and access the data / variables across consecutive calls, I am using a session state object as shown below and it can be successfully accessed in the multiple calls to separate calls by a browser:
// Access the current session object
var blSession = HttpContext.Current.Session;
// create the BL object using the user id
BL accessBL = new BL(userID);
// Store the Bl object in the session object dictionary
blSession["UserBL"] = accessBL;
I have to enable the following setting in the Global.asax, for the Session object to be accessible:
protected void Application_PostAuthorizeRequest()
{
// Enable session state in the web api post authorization
HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
}
Issue comes in when the WebAPI shown above has to be accessed via another ASP.Net MVC client, which is separately hosted on a different machine, at that time same consecutive calls do not maintain the state as shown above and thus it leads to an exception, since the consecutive calls rely on session data to proceed.
I have seen a similar issue when I seen the similar issue when I use the Fiddler Debugger, as it gets hosted as a web proxy, so consecutive calls through that too fails, since it does not maintain the state. In my understanding, issue is due to setting the Cookie across domain, which doesn't seem to work across domains due to security reason
I know a workaround is to use an application wide variable like Cache, but please suggest if you have a way to get the SessionState work. Let me know if you need more details.
If you have not setup an alternative way to do SessionState, then the default behavior is to do it InMemory on the server. This is why you are seeing issues when the request is handled by a different ASP.NET server.
Web API calls are meant to be stateless. That is, they should not perform like a classic ASP.NET application that relies on the framework to store user specific information in Session variables across HTTP requests. For each call, pass in a user-specific identifier or token that you can then use to lookup information stored in your backend. You can store this information in your database or a distributed cache like MemCache for faster retrieval.

Signalr webfarm with Backplane out of sync

We have a SignalR application that we built and tested for use on a single web server. The requirements have changed and we need to deploy the application to a webfarm. SignalR supports several backplanes, since the application already uses Sql Server that is what we have implemented. With the introduction of a second web node we ran into an issue with keeping the data that is cached within the Hub synced between the nodes.
Each hub has an internal cache in the form of a DataSet.
private static DataSet _cache; The cache gets populated when a client first requests data, and from there any interaction updates the local cache and the sql server, then notifies all connected clients of the changes.
The backplane handles the broadcast messages between the clients but the other node does not receive a message.
Our first thought was that there might be a method that we could wire up that would triggered from the backplane sending a message to a nodes clients, but we have not seen such a thing mentioned in documentation.
Our second thought was to create a .net client within the hub.
private async void ConnectHubProxy()
{
IHubProxy EventViewerHubProxy = _hubConnection.CreateHubProxy("EventViewerHub");
EventViewerHubProxy.On<string>("BroadcastAcknowledgedEvents", EventIDs => UpdateCacheIsAcknowledged(EventIDs));
EventViewerHubProxy.On<string>("BroadcastDeletedEvents", EventIDs => UpdateCacheIsDeleted(EventIDs));
ServicePointManager.DefaultConnectionLimit = 10;
await _hubConnection.Start();
}
Our questions:
How do we keep the cache in sync?
Is the first thought possible and we missed it in the documentation?
Are there any issues concerns with having a hub connect to itself?
The recommended way to have "state" in a scaleout scenario is to have a source of persistence. So in your case, if you're looking to have a "global-like" cache one way you can implement that is via a database.
By creating a database all your nodes can write/read from the same source and therefore have a global cache.
The reason why having an in-memory cache is not a good idea is because in a web farm, if nodes go down, they then lose all their in-memory cache. By having persistence, it doesn't matter if a nodes been up for days or has just recovered from a "shutdown" based failure, the persistence layer is always there.

Clustered Environment and Session Management (Servlets)

I was reading a book on Java Servlets where I came across HTTPSessionActivationListener. It was specified that in a clustered environment , there can be only one HTTPSession object containing a specific session id. Assume there are 2 nodes A and B in a cluster -
first request goes to node A. Here a HTTPSession S1 is created along with session attributes and response goes back to the client.
Same client sends the subsequent request. This request goes to node B. Now the session object S1 is moved from node A to node B (activated in Node B and passivated in node A).
In this case should the session object along with the attributes be serializable? What happens if it is not serializable?
In order to count the number of active sessions , should the sessions in both nodes be added up to get the actual value? How is this usually done?
Also I guess ServletContext is unique for each JVM. Are the attributes set as part of servletcontext copied to servlet context in all nodes of the cluster?
Usually I've seen people use sticky sessions (provided usually by the load balancer, for example ec2 ELB has this feature: http://shlomoswidler.com/2010/04/elastic-load-balancing-with-sticky-sessions.html), OR the session data is stored in a shared repository, such as a database or NoSQL store.
Spring session seems to be offering a capability called 'Clustered Sessions' and it also has feature to offload the session to a RedIs or GemFire caching solution.
Reference: http://projects.spring.io/spring-session/
Using a caching solution like Infinispan, hazelcast or redis would be the way to go if you want sessions to survive server failure. Application servers provide these function integrated now a days. You can just enable them from admin interface for web/ejb/jms persistance. If you are storing something into session in your code, you can use JCache API to store them on the underlying cache. JCache provides a product independent caching API, makes you code portable across caching solutions.

ASP.NET Web Service very slow when [WebMethod(EnableSession = true)]

I have created a ASMX Web Service which does some Active Directory stuff behind the scene.
As I wish to retain certain information within Web Services under user session, I have decided to put [WebMethod(EnableSession = true)] and start using Session variables.
However, when I turn that option on, the return time from app -> web service -> app has became ridiculously long. (about a minute or more).
If I remove [WebMethod(EnableSession = true)], it is fairly fast.
Anyone know what is going on?
Possible reasons:
Session state is stored out of process (state server/ SQL server) and getting/storing it taking a long time
You are making multiple concurrent requests (including service requests) under the same session. ASP.NET ensures that only one session-full (session read/write) request execute at a time and hence, multiple concurrent requests would queue up.
EDIT :
For #2, obvious solution is to avoid session state use - for example, can you put the relevant information into another store such as cache or database (expensive).
If you are only reading session state in web service then you may take advantage of read-only session state (see IReadOnlySessionState). Read-only session state allows concurrent read-only requests - read/write request will still block all other requests. Now, EnableSession from WebMethod attribute does not support this - it either provides no session or read/write session. So one of the workaround can be to implement your own handler implementing IReadOnlySessionState and then route asmx request to thi handler using a http-module and then switch the handler to default one later. Because your handler requires read-only session state, you will have the read-only session state - see this forum post where such http-module that switches the handler has been given.

Resources