Is it possible for a WCF service to restart itself? - c#

I'm currently working on a WCF service which holds and processes all the data for an application, while a MySql database is used for persistence. The service currently works as a singleton (InstanceContextMode.Single) and supports multiple concurrent calls (ConcurrencyMode.Multiple). I'm not really sure what version of IIS the service is hosted in, but I believe it is IIS 7.5.
The problem is that there are some situations where if an exception occurs (eg.: while releasing ReaderWriterLockSlim locks), the service will be in a unreliable state and data may get corrupted (and written into the database) if users keep calling the service.
Currently I know of two ways of preventing users from calling the service: either closing the InstanceContext object (through OperationContext.Current) or raising an exception in IDispatchMessageInspector.AfterReceiveRequest if the service is in a faulted state. The problem with both of these two ways is that they make the service unavailable until I restart the server/application pool (which I can't, see note below) or re-deploy the service.
Important note: Although I have Full-Trust, the service is currently hosted on a shared server, so I can't restart the server or the entire application pool (if that is possible) because that would restart other people's services as well.
Update:
I tried unloading the AppDomain as #usr suggested, but that doesn't work as well: after unloading it, an exception is raised for every call to the service.
Currently I'm trying to find out what WCF/IIS uses as a condition to decide if the service should be created again. I noticed that in the code generated for the client checks if there is any channel available to communicate with the service; if there isn't, a new one is created. Thus, I tried to close all channels in the service: I tried closing OperationContext.Current.InstanceContext.OutgoingChannels, OperationContext.Current.InstanceContext.IncomingChannels, OperationContext.Current.Channel, and many other properties with "Channel" in their name, all of them with no success.

The way to warm-up anything in IIS prior to version 7.5 is using scheduled console application to ping your web site / services and warm them up. It's not a good fix but it works, it is easy and I saw it on every project which had to deal with this requirement.
Or If you are using IIS 7.5 then
You can use Windows Server AppFabric, it has Auto Stat feature to keep the service always on. But you need to be on IIS 7.5 to install App Fabric.

Related

How to Gracefully Shut Down ASP.Net (not Core)

I have a WCF service application hosted in IIS. On startup, it reads the SQL connection information from the web.config and connects to the SQL Server to get the necessary information to bootstrap the application. If the SQL Server is unavailable for some reason, we want the service to shutdown - which I currently accomplish by throwing an exception.
The problem we have with this is that, if a service fails to start more than N times, IIS helpfully turns off the application pool - which means that, after the SQL Server connection issue is corrected (possibly entirely external to the IIS server), a sysadmin has to think to go an turn the app pool back on.
What I'd like to do is have the service gracefully exit. I know that there are ways to do this with ASP.Net Core (i.e., ways to hook into the lifecycle management of the process and tell it to exit), but have been unable to find anything like that for .Net Framework/ASP.Net.
Is there such an API that I can use?
Turns out that this method is available and works.
https://learn.microsoft.com/en-us/dotnet/api/system.web.hosting.hostingenvironment.initiateshutdown?view=netframework-4.8

Running console applications from a WCF service - where to host it?

Currently working on a .NET solution for an application server. I'm using .NET 4.0 running on Windows Server 2008 R2 with IIS 7.5.
My requirements are:
The application server can run multiple Console applications at once on a schedule - Quartz.net looks like a really good solution to this problem - and is working well for me so far
The application server will also host a web application that will report on jobs (what time they ran, what they did, how long they took etc)
I would like to be able to restart the "service" that is running my jobs and trigger ad hoc jobs from the web interface.
The Service that is running my jobs needs to run all the time
Once this is live I will not have direct access to the machine to restart a Windows Service, but i could potentially setup IIS to be able to do this for me.
WCF Services looks quite promising to me - but I'm not sure where to host it. My current project uses a WCF Service to run console applications using the Quartz.net plugin. Configuration for what to run and when to run it is stored in an oracle database and my WCF service connets directly to the database to retrieve this information (not sure if that is the intended use of WCF).
If I host the WCF Service in IIS / WAS then running the console applications might be a security concern from what I've read. I can keep the WCF service running all the time using appFabric at least. Alternatively I could host it in a Windows Service and allow my web app to consume the WCF service to report on the jobs. I'm concerned about using a Windows Service though as I wont have direct maintenance access to this machine and if it breaks I'm in trouble. I would really like to be able to do the maintenance from a web application. A windows service also feel a little unnecessary given it can be hosted from IIS.
So my question is - is a WCF Service the right approach to this problem or can anyone think of a better approach?
If a WCF service is a good approach - where should I host it so that I can perform maintenance via a web interface given I will not have direct access to the machine itself?
Should the WCF service be the one to start and schedule the jobs?
I think you're overengineering it, possibly.
The Problem: You have a web site which needs to start up jobs on an ad-hoc basis. Other jobs will be run to a fixed schedule. The web site will report on all/any of these jobs.
For running the scheduled jobs, a Windows Service using Quartz is indeed an ideal solution for the fixed schedule part. However, to report on those jobs the data must be collected by the Service and made available. A service can be set up to restart on fail, so you can guarantee that it will always be running (barring a minute or two when it's restarting if it fails - and why should it?. However, any history will be lost unless the Service stores it somewhere it can be retrieve it after a restart.
The simpler solution to the web site getting the history is for the Service to write its data to a database. Then it doesn't worry about a restart: all the history has already been saved, and the data can be read by the web site at any time.
Similarly, if the web site talks directly to the Service (as a WCF Service or otherwise) then what happens if the service is not currently running? The request gets fails until the restart is completed. Frustrating for the user. Alternatively, the web site puts the request into the database. The service monitors the database for requests, and starts jobs appropriately when it sees a new request. If a request is written while the service is not running, when it restarts it will see the request(s) in the DB and execute them.
So I think using a WCF service is overkill, and actually introduces some problems: persistence of history, and what to do about requests made while the service is down. These problems don't arise if you go the way I've described.
Cheers -

How to host Windows Service (like) in IIS

How to host a Windows Service in IIS and keep that service runing like it is running on Windows?
Could I use some feature from WCF service?
I've not access to the Windows itself, only to IIS. Inside that service I'll create a thread which at scheduled time will process some data.
In short, you can't.
A more detailed answer is that there are 2 problems:
IIS worker processes are launched only when a HTTP request comes in. This means you can't start your service with the system.
IIS worker processes are recycled (i.e. restarted) on several conditions. For example, a worker process is restarted if no HTTP request comes in for a long time. This means you can't control when your service is shut down, unless you have access to application pool recycling configuration. Keep in mind that the recycling logic only ensures that all pending HTTP requests are complete, but does not await all background threads to complete.
You can come with a partial solution this way:
Create a WCF service method that checks if your long-running thread is alive and if not, starts it.
Create a very simple windows service that periodically (once in 5 seconds) calls that method. Deploy the service somewhere, e.g. on your own machine.
The only question that remains is: do you really need to avoid windows services? Could you find a place to host the service? There are some use cases when a windows service is the best or even the only way.
You cant, in a nut shell.
However you can make use of the health monitoring API specifically the heartbeat functionality. see:
http://msdn.microsoft.com/en-us/library/system.web.management.webheartbeatevent.aspx
for details on the class you will need to implement to be called when there is work to do
also this answer on SO might help
Understanding heartbeat in ASP.NET health monitoring
Once you have implemented a webheartbeatevent derived class you can check your db or what ever you want to check if there is work to do.
A better solution IMHO is to scrap the service entirely and redesign the system to be 100% web based, as services become a deployment and maintenance nightmare. as i assume you are now finding out...

Azure: Intra-WebRole Communication (netTcpBinding) with Full-IIS

I need to change some configuration settings on-the-fly in a Windows Azure project - and they need to be changed via a web service call (updating the application's configuration either via the platform api or the Azure Management site isn't an option here).
The project has multiple web and worker roles - all of which will need to know about the new configuration when it is changed.
The configuration is persisted to durable storage, and it's also cached during runtime in a static variable.
My solution was to create an internal (tcp) endpoint on my roles, and use that to loop through all of the roles and instances within those roles, create a client on the fly, and tell the instance about the new setting. (pretty much identical to: http://msdn.microsoft.com/en-us/gg457891)
At first I started a ServiceHost in the WebRole's RoleEntryPoint... and I was confused why everything seemed to be working fine when I stepped through the communications (the static variables where getting set correctly) - yet when I'd make other webservice calls, the static variable seemed to have "forgotten" what I set it to.
This was the case both locally, and in the Azure staging environment.
At this point I realized that because we're using full-IIS mode, the RoleEntryPoint and the Web Services were running in two separate processes - one in Azure's stub, and one in IIS.
"Not a problem" I said, I'll simply move the line of code which starts the ServiceHost from my RoleEntryPoint into the global.asax - at which point the ServiceHost will have been started in the same process as the rest of the site - and the static variables would be the same ones.
Here's where I'm having a problem; This works great on my local machine running in the dev environment. As soon as I deploy to staging I start getting error emails saying the channel used to connect to the service can't be closed because it's in a "faulted state".
Question:
What's different about Azure vs. Dev environment that is causing this?
How can I fix or workaround the problem?
Does anyone have any general advice on how I should go about obtaining a more descriptive error... do I have to enable full wcf diagnostics in Azure to get this, or is there some other way I can get at the exception details?
Follow-Up:
Via remote desktop i've learned several interesting things:
Non-HTTP Activation isn't installed by default on Azure WebRoles. I believe this can be overcome via a startup script:
start /w pkgmgr /iu:WCF-NonHTTP-Activation;
The website created in IIS by the web role doesn't have the net.tcp protocol enabled by default. I also believe this can be overcome with a startup script:
%systemroot%\system32\inetsrv\appcmd.exe set app "Website Name Here" /enabledProtocols:https,http,net.tcp
I haven't had time to take this all the way, as deadlines have forced me to implement some workarounds temporarily.
Some useful links related to this topic:
http://msdn.microsoft.com/en-us/magazine/cc163357.aspx
http://forums.iis.net/t/1160443.aspx
http://msdn.microsoft.com/en-us/library/ms731053.aspx
http://labs.episerver.com/en/Blogs/Paul-Smith/Dates/2008/6/Hosting-non-HTTP-based-WCF-applications-in-IIS7/
UPDATE (6/27/2011):
Amazingly, someone at Microsoft (whose blog I commented on) actually got me an answer on this.
The Azure & WCF teams updated this post:
http://blogs.msdn.com/b/windowsazure/archive/2011/06/27/hosting-services-with-was-and-iis-on-windows-azure.aspx
The link contains all of the information you need to get going with this.
And a HUGE thanks goes to Yavor Georgiev, the MSFT PM with the win.
It's been quite a while since I've asked the question, and no answers, so let me leave this:
Per my follow-ups in the post, there are ways of making this work... but they are complicated and difficult to implement.
For WORKER ROLES, netTcpBinding works perfectly. No issues here. Go ahead and use it.
For WEB ROLES, you've got problems.But netTcpBinding is what you need to use for exposing internal endpoints. What to do?
Well, here's what I did:
Start netTcpBinding service in your RoleEntryPoint using ServiceHost.
Create standard WCF service in your web role using SOAP / JSON / Whatever you want.
When you receive requests through your netTcpBinding, proxy them along to the WCF service on the loopback adapter.
Properly secure your "internal" WCF service with SSL client certs.
It's not perfect... but it works, and it's not terrible.
I suspect that needing to do this kind of thing isn't super common, and I really can't think of any reason why you'd need to other than to dynamically modify settings at runtime... which means you're not slamming these services like crazy.
Obviously, YMMV.
I had a miserable time getting HTTP working between instances in staging, and gave up when it looked like I needed to mess around with netsh to give my processes permission to listen via an HttpListener (sheesh!). So I switched to TCP via sockets. HTTP just adds overhead in a point-to-point communication scenario like this.

When do we use windows service?

Are there situations that we should use a windows service ?
I am building a client-server project (c#) and the server supposed to work alone without any user so someone advised me to use a windows service to run the server, is this right ? or there are a better solutions ?
Windows services are normally used when an application needs to continuously run. For example if they need to:
Wait for incoming requests. (Like through remoting or wcf)
Monitor a queue, file system etc.
If a program just needs to run periodically, like once a day. It is normally easier to create a scheduled task.
In your situation I would use a service for the following reasons:
You don't need to have a session running. This is good for security, and also reduces overhead on the server.
You get some of the managment commands built in for free
Start
Stop
Pause
Continue
You can handle server events such as shutdown.
Windows service can start running as soon as the machine is powered up, which makes ideal for running as a server, http server for example. No one is required to login.
You should create a Windows Service to run code in the background, without user interaction.
For example, a Windows Service will run even if no-one is logged on.
Any server that accepts connections (such as a mail, web, or FTP server) should usually be a Windows Service.
Well, a Windows Service provides a full framework for your application to work and to remain active while you want it to, so I think its ok.
Windows services are the right thing to use for something that should run all of the time, whether or not a user is logged in.
If you need something to run without an active user logged in, you need to use a windows service.
When you need the application to start running even when no one has physically logged into the machine, which is common with server machines, a service is a good candidate in this case. Especially because the service can be configured to auto start, which means the service will start when the machine is rebooted withut human intervention.
If however you are wanting to host web services (WCF) while a service is an option, you might consider hosting in IIS, this relieves you of writing the actual hosting code etc.

Categories

Resources