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.
Related
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.
I am creating a web app. I want to create a listening service (TCP) that listens continuously and updates web page according to that.
A Windows service or a WCF service?
At the end I just want a background service that listens on a socket continuously and update data in database. and when database is updated I will use signal r to show that in my page.
Right now I am trying with WCF but I am wondering if it can be done with Windows service also. And right now this application will work on LAN. But in the future, it can also be in the cloud.
First of all, it is important to understand that a Windows service and a WCF service are not the same.
A Windows service is a specialized executable that runs in the background on Windows.
A WCF service is a specialized piece of code that exposes some functionality through a well-defined endpoint. It does not run on its own, but instead must be hosted by some parent process, like IIS, a desktop application, or even a Windows service.
In thinking about the problem you've described, I suppose the most fundamental question to ask is whether or not you have control over the data that will be received via the TCP connection. WCF is built on the notion of the ABCs (Address, Binding, and Contract), all of which have to match in order to facilitate data exchange between WCF endpoints. For example, if you wish to expose a WCF endpoint via IIS that accepts TCP connections from some remote WCF endpoint, the remote WCF endpoint needs to send data to your IIS-hosted WCF endpoint using the agreed-upon data contract. Absent that, WCF will not work. So, if you cannot define the data contract to be used between WCF endpoints, then you'll need to find another option. An option that will work is to open a TCP listener within a Windows service, process the data as it is received, update your database, and listen for more data.
================================================
By way of example, I work on a project that has a front-end desktop application that communicates with a back-end Windows service. We build both the application and the Windows service, so we have full control over the data exchange between the two processes. At one point in time, we used WCF as the mechanism for data exchange. The Windows service would host a WCF service that exposed a NetNamedPipeBinding, which we later on changed to NetTcpBinding to get around some system administration issues. The application would then create its own endpoint to communicate with the WCF service being hosted within the Windows service.
This worked fine.
As our system got more mature, we needed to start sending more and more information from the Windows service to the application. If I recall correctly, I believe we experimented with streaming within WCF and concluded that the overhead was not something we could tolerate. So, we used WCF to exchange commands and status information between the application and the Windows service, but we simultaneously used a TCP socket connection to stream the data from the Windows service to the application.
This worked fine.
When we got a chance to update the Windows service software, we decided that it would be better to have a single communication mechanism between the Windows service and the application. So, we replaced WCF altogether with a TCP socket connection that uses a homegrown messaging protocol to exchange information in both directions - application to Windows service and Windows service to application.
This works fine and is the approach we've used for a couple of years now.
HTH
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
I'm sure that was a confusing enough title.
I have a long running Windows service dealing with things happening in the world. This service is my canonical source of truth for the rest of my system. Now I want to slap a web interface onto this so the clients can see what is actually going on. At first this would simply be a MVC5 application with some Web API stuff. Then I plan to use SignalR 2.0 and Ember.js to make this application more interactive and "realtime".
The client communicates with the Windows Service over named pipes using WCF. A client (such as a web app) could request an instance of for example IEventService, would be given a WCF proxy client, and could read about events through this interface. Simple enough.
However, a web application basically just exists in the sense that it responds to requests from the user. The way I understand it, this is not the optimal environment for a long lived WCF client proxy to raise events in, and thus I wonder how to host my SignalR stuff. Keep in mind that a user would log in to the MVC5 site, but through the magic of SignalR, they will keep interacting with the service without necessarily making further requests to the website.
The way I see it, there are two options:
1) Host SignalR stuff as part of the web app. Find a way to keep it "long-running" while it has active clients, so that it can react to events on the WCF client proxy by passing information out to the connected web users.
2) Host SignalR stuff as part of my Windows service. This is already long-running, but I know nada about OWIN and what this would mean for my project. Also the SignalR client will have to connect to a different port than where the web app was served from, I assume.
Any advice on which is the right direction to go in? Keep in mind that in extreme cases, a web user would log in when they get to work in the morning, and only have signalr traffic going back and forth (i.e. no web requests) for a full work day, before logging out. I need them to keep up with realtime events all that time.
Any takers? :)
The benefit of self-hosting as part of your Windows service is that you can integrate the calls to clients directly with your existing code and events. If you host the SignalR server separately, you'd have another layer of communication between your service and the SignalR server.
If you've already decided on using WCF named pipes for that, then it probably won't make a difference whether you self-host or host in IIS (as long as it's on the same machine). The SignalR server itself is always "long-running" in the sense that as long as a client is connected, it will receive updates. It doesn't require manual requests from the user.
In any case, you'll probably need a web server to serve the HTML, scripts and images.
Having clients connected for a day shouldn't be a problem either way, as far as I can see.
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.