简体   繁体   中英

Using Web API for a Windows Service to Receive Commands and Perform Tasks via Polling?

I have a project where I need to create a windows service that, when instructed via a command, will perform various tasks. This server would run on multiple servers and would effectively perform the same kind of tasks when requested.

For example, I would like to have a Web API service that listens for requests from the servers.

The service running on the server would send a query to Web API every 25 secs or so and pass to it its SERVERNAME. The Web API logic will then look up the SERVERNAME and look for any status updates for various tasks... IE, if a status for a DELETE command is a 1, the service would delete the folder containing log files... if a status for a ZIP command is a 1, the service would zip the folder containing log files and FTP them to a centralized location.

This concept seems simple enough, and I think I need a nudge to tell me if this sounds like a good design. I'm thinking of using .NET 4.5 for the Windows Service, so that I can use the HttpClient object and, of course, .NET 4.5 for the Web API/MVC project.

Can someone please get me started on what a basic Web API woudld look like provide status updates to the Windows services that are running and issue commands to them...

I'm thinking of having a simple MVC website that folks will have a list of servers (maybe based on a simple XML file or something) that they can click various radio buttons to turn on "DELETE", "ZIP" or whatever, to trigger the task on the service.

I do something similar. I have a main Web API (a Windows Service) that drives my application and has a resource called /Heartbeat .

I also have a second Windows Service that has a timer fire every 30 seconds. Each time the timer fires it calls POST /heartbeat . When the heartbeat request is handled, it goes looking for tasks that have been scheduled.

The advantage of this approach is that the service makes the hearbeat request is extremely simple and never has to be updated. All the logic relating to what happens on a heartbeat is in the main service.

The guts of the service are this. It's old code so it is still using HttpWebRequest instead of HttpClient, but that's trivial to change.

 public partial class HeartbeatService : ServiceBase {
        readonly Timer _Timer = new System.Timers.Timer();

        private string _heartbeatTarget;


        public HeartbeatService() {
            Trace.TraceInformation("Initializing Heartbeat Service");
            InitializeComponent();
            this.ServiceName = "TavisHeartbeat";
        }

        protected override void OnStart(string[] args) {
            Trace.TraceInformation("Starting...");
            _Timer.Enabled = true;

            _Timer.Interval = Properties.Settings.Default.IntervalMinutes * 1000 * 60; 
            _Timer.Elapsed += new ElapsedEventHandler(_Timer_Elapsed);

            _heartbeatTarget = Properties.Settings.Default.TargetUrl; 
        }

        protected override void OnStop() {
            _Timer.Enabled = false;
        }

        private void _Timer_Elapsed(object sender, ElapsedEventArgs e) {
            Trace.TraceInformation("Heartbeat event triggered");
            try {

                var httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(_heartbeatTarget);
                httpWebRequest.ContentLength = 0;
                httpWebRequest.Method = "POST";
                var response = (HttpWebResponse)httpWebRequest.GetResponse();
                Trace.TraceInformation("Http Response : " + response.StatusCode + " " + response.StatusDescription); 
            } catch (Exception ex) {
                string errorMessage = ex.Message;
                while (ex.InnerException != null) {
                    errorMessage = errorMessage + Environment.NewLine + ex.InnerException.Message;
                    ex = ex.InnerException;
                }
                Trace.TraceError(errorMessage);
            }

        }


    }

You can do it with ServiceController.ExecuteCommand() method from .NET. With the method you can sand custom command to windows' service. Then in your service you need to implement ServiceBase.OnCustomCommand() to serve incomming custom command event in service.

const int SmartRestart = 8;

...

//APPLICATION TO SEND COMMAND
service.ExecuteCommand(SmartRestart);

...

//SERVICE
protected override void OnCustomCommand(int command)
{
    if (command == SmartRestart)
    {
        // ...
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM