How does Signal-R fit in the IIS activation model? - asp.net

I am learning Signal-R, and this is something that has been in my head during all time.
How does Signal-R fits in the IIS/ASP.NET life cycle?
How long does the Hubs live (I see they have re-connection semantics)?
Does IIS does prevent the shutdown of an AppDomain that has a persistent connection?
It is my understanding that IIS is designed to handle request-response scenarios. A request hits IIS, this finds the AppDomain, activate it, and then pass the request to it. And after an idle time, shutdown the AppDomain. If the request takes too long, a timeout exception is thrown.
Now let´s imagine that I have another application that broadcast information through a TCP socket. I want my javascript clients to get that information in real time, so I create a Signal-R web application. I can create a TCP client on application start, but what does guarantee that IIS is not going to shutdown the whole thing after some time with inactivity?
I could self host the Signal-R app in a window service, but then I would have to use a different port, enable cross domain, etc... Many problems for deployment. But, I am concerned about using an ASP.NET MVC application for this, since it looks to me like fitting a driving wheel in a motorbike.
Cheers.

SignalR in IIS/ASP.NET Lifecycle
SignalR uses Owin: http://owin.org/
A good article on Owin here: http://msdn.microsoft.com/en-us/magazine/dn451439.aspx
Hub object lifetime
From the SignalR docs: http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-server#transience:
You don't instantiate the Hub class or call its methods from your own code on the server; all that is done for you by the SignalR Hubs pipeline. SignalR creates a new instance of your Hub class each time it needs to handle a Hub operation such as when a client connects, disconnects, or makes a method call to the server.
Because instances of the Hub class are transient, you can't use them to maintain state from one method call to the next. Each time the server receives a method call from a client, a new instance of your Hub class processes the message. To maintain state through multiple connections and method calls, use some other method such as a database, or a static variable on the Hub class, or a different class that does not derive from Hub. If you persist data in memory, using a method such as a static variable on the Hub class, the data will be lost when the app domain recycles.
Your long running TCP client
This is not a problem with SignalR. Your TCP client can be shutdown by IIS: http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx/
I would rather make the TCP client run in a windows service. The TCP client receives TCP broadcast messages and forwards the messages to the Hub using the SignalR .NET client.

Hubs are recreated on each SignalR request, so if you need a persistent connection you may have to look into using static vars or dictionary to hold state. But as you point ASP.NET can restart for a variety of reasons.
It depends on what persistancy you really need. If you have a connection that MUST stay alive at all times and cannot be torn down and reestablished then hosting in IIS is not the right choice. However, if you can re-establish the same connection after a shutdown, then maybe this can still work.
You can do quite a bit in making sure that ASP.NET apps don't shut down in recent versions of IIS:
http://weblog.west-wind.com/posts/2013/Oct/02/Use-IIS-Application-Initialization-for-keeping-ASPNET-Apps-alive
If that's not enough for you running as a separate service is an option. If you run as a service on the same IP address there are no cross domain concerns. Here's more info on running SignalR using a Windows Service:
http://weblog.west-wind.com/posts/2013/Sep/04/SelfHosting-SignalR-in-a-Windows-Service

Related

Configuring Azure's Event Hub to receive events from ASP.NET MVC web application

Can someone point me in the right direction on how to configure network settings within event hub so i can successfully send data via the ASP.NET MVC application while running locally (localhost) as well as when I deploy the application in azure's dev/qa/production web environment.
I have build a proof of concept console application in .NET locally and on Azure's EventHub side added my IP address within Networking/Firewall settings, and have no issue sending data and receiving data from a local machine.
But when I try the same code in the ASP.NET MVC web application, the page just hangs on CreateBatchAsync() method and does not return any exception..
var producerClient = new EventHubProducerClient(connectionString, eventHubName);
EventDataBatch eventBatch = await producerClient.CreateBatchAsync();
eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes("Event 1z at " + DateTime.Now.ToString())));
await producerClient.SendAsync(eventBatch);
Any help would be appreciated.
Thanks
The call to CreateBatchAsync is the first point in your code to request a network operation and, consequently, will trigger creation of the connection and link to the Event Hubs service. The connection attempt has a timeout associated with it which is 60 seconds in the default configuration that you're using. Depending on the error that it is encountering, you may see retries take place, each of which would have a 60 second timeout. With the default configuration, this would look like a 3 minute hang. (60 seconds * 3 attempts)
The most common connection issue in an enterprise environment is that the ports needed for AMQP over TCP (5671/5672) are not open. Changing the transport to AMQP over WebSockets often helps, as it will use port 443 and may be routed through a proxy, if needed.
For more information, you may want to look at the sample for configuring Event Hubs clients and the Event Hubs network troubleshooting guide.

SignalR and Web API communication

In one server, I have 2 web applications. One of them is a Web API, and the other one is SignalR. Both apps are hosted in IIS, under 2 different application pulls.
What is the best way to communicate between those 2 web applications? Is using either SignalR, or REST calls viable, for example?
You can use several way;
1) A message queue system would work. Your server is IIS, you can use MSMQ.
2) Alternate to MSMQ, you can use RabbitMQ.
3) As you mentioned, you can use HTTP calls.
4) You have already a SignalR. So you can use it for communication. Write a Hub that the servers join to hub.
Options are depends on your requirement. Backend servers, mostly, communicate with a message queue system. HTTP calls are also acceptable.
The biggest difference between HTTP and a message queue is async calls. For example, When a HTTP call trying to reach an endpoint, it waits for a response and if the server is down, you have to try again until server up. On the other hand, a message queue system uses a queue. Just fire and forget the data. Other side of the connection can get the data whenever the server is ready.
SignalR is too risky for this job.

How to get SignalR Connection to Respect Session Timeout

Using SignalR, it's designed to maintain a long-running connection to the web server. However, I have a scenario where the SignalR connection maintains an open connection to the web server, long after the ASP.Net session has expired. This happens even though neither the client nor the server is sending an data.
How can I set things up so that once the Asp.net session expires, the SignalR connection terminates, freeing up connections on the server?
This is desired because the web servers run on a load balancer, and when taking a server out of the rotation, we need the # of current connections to generally represent the number of active sessions - not SignalR connections that are still kicking just because user left browser open.
SignalR Server does not allow to disconnect a particular client connection (this would be super useful). So the client is responsible to do that.
A workaround would be to add an event listener on the client and disconnect from there, i.e:
hubProxy.On<string>("YouAreUselesLetMeAlone", _ => connection.Dispose());
Obviously, to make this work you need a relation (ConcurrentDictionary?) of asp.net sessions <-> signalr connections, so you can call this method in the correct client when the asp.net session ends.

WCF client per ASP.NET request?

I have WCF service, called by ASP.NET web application. When there is more than one call per page request, is it better to keep client open and share the instance across the whole request, or is it better to create and dispose client per each service call as shown below?
using (var client = new WcfClient())
{
var result = client.Method();
}
If you're using webHttpbinding, wshttpbinding or basicHttpbinding, the default behavior is for each client request (call) to get its own unique connection and instance of the web service object(s). This means that when Client A and B send requests to your web service, each will get it's own instance of the service, instantiated by the hosting program, then disposed of neatly (hopefully) when the response is sent back to the client. The WCF .NET infrastructure and the hosting program take care of all of the creation and destruction of the connections and objects for you, unless you hijack the process and do something fancy.
It's possible to create persistant client sessions that leave a connection open and the service in memory, but I've never tried it. Here's a link to an explanation of how to do it:
WCF sessions with a wsHttpBinding and without windows security
For the last two years, I've worked entirely on WCF client and host software on an industrial scale and there's not much reason to worry about the efficiency of continuously openning and closing connections on a WCF web service. I've benchmarked our tests services with hundreds of concurrent client connections, each uploading and downloading files, and it barely stresses the WCF server's CPU. During our tests, the majority of the stress (as usual) fell on the database side.

Does an asp.net webservice have something like application start and application variables?

I'm developing a webservice that will, when called, notify another program via a tcp connection. My problem is where to store the open tcp connection. The way I understand web services, they start and end with each HTTP Request, with no room for application wide variables, like the open tcp connection.
Please correct me if I'm wrong.
Specifically, in what part of the asmx file, or outside of it, should I place the code for listening for incoming tcp traffic?
Application events in Global.asax should fire for a web service hosted as an application in IIS. You can use these. Keep in mind that they will fire even if a web page and not the web service is accessed in the same application.
You can place the tcp connection as a static member of the service class and make a static constructor that handles the instantiation.
This will create the tcp connection before the first access of the web service is handled and then persist the connection as long as the hosting process is running. The only drawback with that approach is that the tcp connection is process wide. If you host two instances of the web service within the same process (quite unlikely) they will share the same tcp connection.
Fortunately for you, you are wrong.
Application-wide events do fire plus you have the access to all asp.net containers, the Application container for application-level variables, the Session container for session-level variables (if the client side supports cookies, the session id could even be passed in a cookie) and the Items container for request-level variables.
However, whether or not this helps you to store an additional tcp listener (if I understand correcly) is another story, not obvious one.

Resources