NET Core application?
In the example of "N ways to count Dependency injection" to demonstrate the system autoenrollment service, we will find that the output list contains two special services, and their corresponding service interfaces are iapplicationlifetime and ihostingenvironment, respectively. The services we will implement for each of these two interfaces are collectively known as Applicationlifetime and hostingenvironment. We can see from its naming that Applicationlifetime is related to the application's declaration cycle, while hostingenvironment is used to represent the current execution environment, This article focuses on how applicationlifetime relates to the life cycle of the entire aasp.net core application. [This article has been synced to the "ASP. NET Core Framework"]
Directory
First, Applicationlifetime
Second, Webhost's Run method
Third, remote shutdown applications
First, Applicationlifetime
From a named point of view, Applicationlifetime seems to be a description of the current application life cycle, but in fact it exists only to send a corresponding signal or notification to the relevant component when the application is started and closed. As shown in the following code fragment, the Iapplicationlifetime interface has three properties of the CancellationToken type (applicationstarted, Applicationstopping and applicationstopped), if you need to do something before and after the app is automatically and terminated, we can register the corresponding callback on these three CancellationToken objects. In addition to these three types of cancellationtoken properties, the Iapplicationlifetime interface also defines a stopapplication method that we can call to send the signal to close the application and eventually actually close the application.
1:public Interface Iapplicationlifetime
2: {
3: cancellationtoken applicationstarted {get;}
4: cancellationtoken applicationstopping {get;}
5: cancellationtoken applicationstopped {get;}
7: void Stopapplication ();
8:}
The default applicationlifetime used by ASP. NET core is a type with the same name as defined below. You can see that the three properties it implements return the CancellationToken object that is generated by three corresponding CancellationTokenSource. In addition to the Stopapplication method that implements the Iapplicationlifetime interface for sending "shutting down" notifications, this type defines an additional two methods (Notifystarted and notifystopped) for sending " Notifications that have been turned on/off.
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 ();
7: Public CancellationToken applicationstarted
8: {
9: get {return _startedsource.token;}
Ten: }
One: public cancellationtoken applicationstopped
: {
: get {return _stoppedsource.token;}
: }
: Public CancellationToken applicationstopping
: {
: get {return _stoppingsource.token;}
: }
: Public void notifystarted ()
: {
: _startedsource.cancel (false);
: }
: Public void notifystopped ()
: {
: _stoppedsource.cancel (false);
: }
: Public void Stopapplication ()
: {
: _stoppingsource.cancel (false);
: }
32:}
When the webhost is opened due to the execution of the Start method, it will eventually call the Applicationlifetime notifystarted method to send the signal to the application to be successfully launched. I do not know that reader friends are also noticed that webhost only defines the Start method to launch the application, and does not define the stop or Close method to terminate 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;}
6: Public void Start ()
7: {
8: ...
9: _applicationlifetime.notifystarted ();
Ten: }
: Public void Dispose ()
: {
: _applicationlifetime.stopapplication ();
: (this. Services as IDisposable)?. Dispose ();
: _applicationlifetime.notifystopped ();
: }
: ...
19:}
Second, Webhost's Run method
We know that the launch application is ultimately done by invoking the Start method of the host's webhost, but none of the instances we demonstrated previously have explicitly called this method, and we are calling its extension method run. There is no doubt that the webhost run method will definitely invoke the Start method to open webhost, but what is so special about this run method?
The purpose of the Run method, in addition to starting webhost, actually blocks the current process until the app shuts down. We know that the intent of the closure of the application is achieved by using the Applicationlifetime to send the corresponding signal, so the run method will wait until the current thread is blocked until it receives the signal when it starts webhost. The code snippet shown below basically embodies 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 app
8: console.cancelkeypress + = (sender, args) =
9: {
Ten: CTS. Cancel ();
One: args. Cancel = true;
: };
: host. Run (CTS. Token);
: }
: }
: public static void Run (this iwebhost host, CancellationToken token)
: {
: using (host)
: {
: //Show Application Basics
: host. Start ();
: iapplicationlifetime applicationlifetime = host. Services.getservice<iapplicationlifetime> ();
: token. Register (state = (iapplicationlifetime) state). Stopapplication (), applicationlifetime);
: ApplicationLifetime.ApplicationStopping.WaitHandle.WaitOne ();
: }
: }
28:}
The code snippet above also shows another detail. Although webhost implements the IDisposable interface, in principle we need to explicitly call its Dispose method when it is closed. A call to this method is important because its serviceprovider can only be reclaimed when the method is called. However, none of the previous instances of the demo have done so because the run method automatically helps reclaim the specified webhost.
third, remote shutdown applications
Since webhost will use Applicationlifetime to wait for the stopping signal to be sent after booting, this means that the ASP. The core pipeline server and any middleware can call Applicationlifetime's stopapplication at the appropriate time to close the application. For the Kestrelserver introduced in the "leader" position of the server in the pipeline, we know that when constructing this object, we must specify a Applicationlifetime object, whose fundamental purpose is to send some unrecoverable errors. It can use this object to close the app.
Next we demonstrate how to use this Applicationlifetime object in a middleware to implement remote shutdown of the application, so we name the middleware Remotestopmiddleware. Remotestopmiddleware the principle of implementing a remote shutdown application is simple, we send a head request remotely and add a header called "stop-application" to the request to attempt to close the application. The middleware will close the application after receiving this request, and a "application-stopped" header will be added to the response to indicate 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";
7: Public Remotestopmiddleware (requestdelegate next)
8: {
9: _next = next;
Ten: }
: Public Async Task Invoke (HttpContext context, iapplicationlifetime Lifetime)
: {
: if (context. Request.method = = "HEAD" && context. Request.headers[requestheader]. FirstOrDefault () = = "Yes")
: {
: context. RESPONSE.HEADERS.ADD (Responseheader, "Yes");
: lifetime. Stopapplication ();
: }
: Else
: {
: await _next (context);
: }
: }
24:}
The code snippet shown above is a complete definition of the middleware for Remotestopmiddleware, and the implementation logic is simple, and there is no need to explain it at all. In a console application, we started a Hello World application with the following program and registered this remotestopmiddleware middleware. After launching this app, we send three requests to the destination address with fiddler, where the first and third normal get requests are made, and the second is to remotely close the app's head request. As shown below is the content of three requests and responses, the third request returns a response with a status code of 502 because the application was closed by a second request.
1://1th Request and response
2:get http://localhost:5000/HTTP/1.1
3:user-agent:fiddler
4:host:localhost:5000
6:http/1.1 OK
7:date:sun, 06:15:03 GMT
8:transfer-encoding:chunked
9:server:kestrel
11:hello world!
13://2nd Request and Response
14:head http://localhost:5000/HTTP/1.1
Stop-application:yes
16:user-agent:fiddler
17:host:localhost:5000
19:http/1.1 OK
20:date:sun, 06:15:34 GMT
21:server:kestrel
Application-stopped:yes
24://3rd Request and Response
25:get http://localhost:5000/HTTP/1.1
26:user-agent:fiddler
27:host:localhost:5000
502 Fiddler-connection Failed
30:date:sun, 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
: [Fiddler] the connection to ' localhost ' failed ...
NET Core application?