How can I remotely close an ASP. NET Core application ?, Asp. netcore

Source: Internet
Author: User
Tags webhost

How can I remotely close an ASP. NET Core application ?, Asp. netcore

In the "N methods of resource dependent injection" demonstration system automatically registers the service instance, we will find that the output list contains two special services, their corresponding service interfaces are IApplicationLifetime and IHostingEnvironment. Services that implement these two interfaces are collectively referred to in ApplicationLifetime and HostingEnvironment. We can see from its name that ApplicationLifetime is related to the application declaration cycle, while HostingEnvironment is used to represent the current execution environment. In this article, we will learn about ApplicationLifetime and the entire AASP. NET Core application lifecycle. [This Article has been synchronized to ASP. NET Core framework secrets]

 

Directory
1. ApplicationLifetime
Ii. WebHost Run Method
3. remotely close the application

1. ApplicationLifetime

From the perspective of naming, ApplicationLifetime seems to be a description of the current application lifecycle, in fact, it only serves to send signals or notifications to related components when the application is started or shut down. As shown in the following code snippet, The IApplicationLifetime interface has three CancellationToken-type attributes (ApplicationStarted, ApplicationStopping, and ApplicationStopped). If you need to perform an operation before and after the application is automatically terminated, we can register the corresponding callback on these three CancellationToken objects. In addition to the three types of CancellationToken attributes, the IApplicationLifetime interface also defines a StopApplication method. We can call this method to send a signal to close the application and eventually close the application.

   1: public interface IApplicationLifetime
   2: {
   3:     CancellationToken ApplicationStarted { get; }
   4:     CancellationToken ApplicationStopping { get; }
   5:     CancellationToken ApplicationStopped { get; }
   6:  
   7:     void StopApplication();
   8: }

The default ApplicationLifetime used by ASP. NET Core is a type with the same name defined as follows. It can be seen that the CancellationToken object returned by the three attributes it implements is generated through three corresponding CancellationTokenSource. In addition to the StopApplication method that implements the IApplicationLifetime interface, this type also defines two additional methods (NotifyStarted and NotifyStopped) to send notifications with "enabled/disabled.

   1: public class ApplicationLifetime : IApplicationLifetime
   2: {
   3:     private readonly CancellationTokenSource _startedSource = new CancellationTokenSource();
   4:     private readonly CancellationTokenSource _stoppedSource = new CancellationTokenSource();
   5:     private readonly CancellationTokenSource _stoppingSource = new CancellationTokenSource();    
   6:  
   7:     public CancellationToken ApplicationStarted
   8:     {
   9:         get { return _startedSource.Token; }
  10:     }
  11:     public CancellationToken ApplicationStopped
  12:     {
  13:         get { return _stoppedSource.Token; }
  14:     }
  15:     public CancellationToken ApplicationStopping
  16:     {
  17:         get { return _stoppingSource.Token; }
  18:     }
  19:  
  20:     public void NotifyStarted()
  21:     {
  22:         _startedSource.Cancel(false);
  23:     }
  24:     public void NotifyStopped()
  25:     {
  26:         _stoppedSource.Cancel(false);
  27:     }
  28:     public void StopApplication()
  29:     {
  30:         _stoppingSource.Cancel(false);
  31:     }
  32: }

When the WebHost is enabled because of the execution of the Start method, it will eventually call the notiflifelifetime NotifyStarted method to send the signal that the application is successfully started. I don't know whether the readers have noticed that WebHost only defines the Start method for starting an application and does not define the Stop or Close method for terminating the application, it only calls the StopApplication method of ApplicationLifetime in the Dispose method.

   1: public class WebHost : IWebHost
   2: {    
   3:     private ApplicationLifetime _applicationLifetime;
   4:     public IServiceProvider Services { get;}
   5:  
   6:     public void Start()
   7:     {
   8:        ...
   9:         _applicationLifetime.NotifyStarted();
  10:     }
  11:  
  12:     public void Dispose()
  13:     {
  14:         _applicationLifetime.StopApplication();
  15:         (this.Services as IDisposable)?.Dispose();
  16:         _applicationLifetime.NotifyStopped();
  17:     }
  18:     ...
  19: }
Ii. WebHost Run Method

We know that starting an application is done by calling the Start method of the WebHost that acts as the host, but none of the instances we demonstrated previously explicitly call this method, we call its extension method Run. Without a doubt, the WebHost Run method will certainly call the Start method to Start WebHost. But what are the special features of this Run method?

In addition to starting WebHost, the Run method actually blocks the current process until the application is closed. We know that the purpose of application shutdown is to use ApplicationLifetime to send the corresponding signal, so when this Run method starts WebHost, it waits until it receives the signal by blocking the current thread. The code snippets shown below basically reflect the implementation logic of the two extension methods Run.

   1: public static class WebHostExtensions
   2: {
   3:     public static void Run(this IWebHost host)
   4:     {
   5:         using (CancellationTokenSource cts = new CancellationTokenSource())
   6:         {
7: // Ctrl + C: Close the application
   8:             Console.CancelKeyPress +=  (sender, args) =>
   9:             {
  10:                 cts.Cancel();
  11:                 args.Cancel = true;
  12:             };
  13:             host.Run(cts.Token);
  14:         }
  15:     }
  16:  
  17:     public static void Run(this IWebHost host, CancellationToken token)
  18:     {
  19:         using (host)
  20:         {
21: // display basic application information
  22:             host.Start();
  23:             IApplicationLifetime applicationLifetime = host.Services.GetService<IApplicationLifetime>();
  24:             token.Register(state => ((IApplicationLifetime)state).StopApplication(), applicationLifetime);
  25:             applicationLifetime.ApplicationStopping.WaitHandle.WaitOne();
  26:         }
  27:     }
  28: }

The above code snippet also shows another detail. Although WebHost implements the IDisposable interface, in principle, we need to explicitly call its Dispose method when disabling it. It is very important to call this method because its ServiceProvider can only be recycled and released when this method is called. However, this is not done for all the previously demonstrated instances, because the Run method will automatically help recycle and release the specified WebHost.

3. remotely close the application

Since WebHost will use ApplicationLifetime to wait for the Stopping signal to be sent after it is started, this means to form ASP. the server of the NET Core pipeline and any middleware can call the StopApplication of ApplicationLifetime as appropriate to close the application. For the KestrelServer introduced in "the server's leading position in the pipeline", we know that when constructing this object, we must specify an ApplicationLifetime object, the fundamental purpose is that when an error cannot be recovered is sent, the object can be used to close the application.

Next, we will demonstrate how to use this ApplicationLifetime object in a middleware to remotely close the application. Therefore, we name this middleware RemoteStopMiddleware. RemoteStopMiddleware: the principle of implementing remote Application shutdown is very simple. We send a Head request remotely and add a header named "Stop-Application" to the request to transfer it to the intent of shutting down the Application, after the middleware receives the request, the Application is closed, and a "Application-Stopped" header is added to the response, indicating that the Application has been closed.

   1: public class RemoteStopMiddleware
   2: {
   3:     private RequestDelegate _next;
   4:     private const string     RequestHeader      = "Stop-Application";
   5:     private const string     ResponseHeader     = "Application-Stopped";
   6:  
   7:     public RemoteStopMiddleware(RequestDelegate next)
   8:     {
   9:         _next = next;
  10:     }
  11:  
  12:     public async Task Invoke(HttpContext context, IApplicationLifetime lifetime)
  13:     {
  14:         if (context.Request.Method == "HEAD" && context.Request.Headers[RequestHeader].FirstOrDefault() == "Yes")
  15:         {
  16:             context.Response.Headers.Add(ResponseHeader, "Yes");
  17:             lifetime.StopApplication();
  18:         }
  19:         else
  20:         {
  21:             await  _next(context);
  22:         }
  23:     }
  24: }

The code snippet shown above is the complete definition of the RemoteStopMiddleware middleware. The implementation logic is simple and there is no need to explain it again. In a console application, we start a Hello World application using the following program and register the RemoteStopMiddleware middleware. After the application is started, we use Fiddler to send three requests to the target address, the first and third common GET requests, and the second to remotely close the application's HEAD requests. The following shows the three request and response content. Because the application is disabled by the second request, a 502 response is returned for the third request.

1: // 1st requests and responses
   2: GET http://localhost:5000/ HTTP/1.1
   3: User-Agent: Fiddler
   4: Host: localhost:5000
   5:  
   6: HTTP/1.1 200 OK
   7: Date: Sun, 06 Nov 2016 06:15:03 GMT
   8: Transfer-Encoding: chunked
   9: Server: Kestrel
  10:  
  11: Hello world!
  12:  
13: // 2nd requests and responses
  14: HEAD http://localhost:5000/ HTTP/1.1
  15: Stop-Application: Yes
  16: User-Agent: Fiddler
  17: Host: localhost:5000
  18:  
  19: HTTP/1.1 200 OK
  20: Date: Sun, 06 Nov 2016 06:15:34 GMT
  21: Server: Kestrel
  22: Application-Stopped: Yes
  23:  
24: // 3rd requests and responses
  25: GET http://localhost:5000/ HTTP/1.1
  26: User-Agent: Fiddler
  27: Host: localhost:5000
  28:  
  29: HTTP/1.1 502 Fiddler - Connection Failed
  30: Date: Sun, 06 Nov 2016 06:15:44 GMT
  31: Content-Type: text/html; charset=UTF-8
  32: Connection: close
  33: Cache-Control: no-cache, must-revalidate
  34: Timestamp: 14:15:44.790
  35:  
  36: [Fiddler] The connection to 'localhost' failed...

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.