Asp.NetCore遠程自啟動、重啟、關閉實現


一、背景

NetCore作為微服務可以注冊到服務中心,服務中心可以遠程啟動、重啟、關閉該微服務

 

二、實現

1、創建一個NetCore 2.0 WebApi項目

2、創建一個進程去管理NetCore程序進程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
public  class  ApplicationManager
     {
 
         private  static  ApplicationManager _appManager;
         private  IWebHost _web;
         private  CancellationTokenSource _tokenSource;
         private  bool  _running;
         private  bool  _restart;
 
         public  bool  Restarting => _restart;
 
         public  ApplicationManager()
         {
             _running =  false ;
             _restart =  false ;
         
         }
 
         public  static  ApplicationManager Load()
         {
             if  (_appManager ==  null )
                 _appManager =  new  ApplicationManager();
 
             return  _appManager;
         }
 
         public  void  Start()
         {
             if  (_running)
                 return ;
 
             if  (_tokenSource !=  null  && _tokenSource.IsCancellationRequested)
                 return ;
 
             _tokenSource =  new  CancellationTokenSource();
             _tokenSource.Token.ThrowIfCancellationRequested();
             _running =  true ;
 
             _web =  new  WebHostBuilder()
             .UseKestrel()
             .UseContentRoot(Directory.GetCurrentDirectory())
             .UseIISIntegration()
             .UseStartup<Startup>()
             .Build();
 
             _web.Run(_tokenSource.Token);
         }
 
         public  void  Stop()
         {
             if  (!_running)
                 return ;
 
             _tokenSource.Cancel();
             _running =  false ;
         }
 
         public  void  Restart()
         {
             Stop();
 
             _restart =  true ;
             _tokenSource =  null ;
         }
     }

  3、把ApplicationManager加入到Main中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public  static  void  Main( string [] args)
         {
             try
             {
                 var  appManager = ApplicationManager.Load();
 
                 do
                 {
                     appManager.Start();
                 while  (appManager.Restarting);
 
 
             }
             catch  (Exception ex)
             {
 
             }
         }

  4、在程序的ValuesController中實現重啟、關閉的Api

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Threading.Tasks;
using  Microsoft.AspNetCore.Mvc;
 
namespace  NetCoreWebApiDemo.Controllers
{
     [Route( "api/[controller]" )]
     public  class  ValuesController : Controller
     {
         private  ApplicationManager appManager = ApplicationManager.Load();
 
         // GET api/values
         [HttpGet]
         public  IEnumerable< string > Get()
         {
             return  new  string [] {  "value1" "value2"  };
         }
 
         // GET api/values/5
         [HttpGet( "{cmd}" )]
         public  string  Get( string  cmd)
         {
             switch  (cmd)
             {
                 case  "restart" : appManager.Restart();  break ;
                 case  "stop" : appManager.Stop();  break ;
                 case  "start" : appManager.Start();  break ;
             }
             return  cmd;
         }
 
 
 
         // POST api/values
         [HttpPost]
         public  void  Post([FromBody] string  value)
         {
         }
 
         // PUT api/values/5
         [HttpPut( "{id}" )]
         public  void  Put( int  id, [FromBody] string  value)
         {
         }
 
         // DELETE api/values/5
         [HttpDelete( "{id}" )]
         public  void  Delete( int  id)
         {
         }
     }
}

6、給程序啟動和停止加入日志標簽

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Threading.Tasks;
using  Microsoft.AspNetCore.Builder;
using  Microsoft.AspNetCore.Hosting;
using  Microsoft.Extensions.Configuration;
using  Microsoft.Extensions.DependencyInjection;
using  Microsoft.Extensions.Logging;
using  Microsoft.Extensions.Options;
 
namespace  NetCoreWebApiDemo
{
     public  class  Startup
     {
         public  Startup(IConfiguration configuration)
         {
             Configuration = configuration;
         }
 
         public  IConfiguration Configuration {  get ; }
 
         // This method gets called by the runtime. Use this method to add services to the container.
         public  void  ConfigureServices(IServiceCollection services)
         {
             services.AddMvc();
         }
 
         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
         public  void  Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime lifetime)
         {
             if  (env.IsDevelopment())
             {
                 app.UseDeveloperExceptionPage();
             }
 
             app.UseMvc();
 
             lifetime.ApplicationStarted.Register(OnStart); //1:應用啟動時加載配置,2:應用啟動后注冊服務中心
             lifetime.ApplicationStopped.Register(UnRegService); //應用停止后從服務中心注銷
         }
         private  void  OnStart()
         {
             LoadAppConfig();
             RegService();
         }
         private  void  LoadAppConfig()
         {
             //加載應用配置
             Console.WriteLine( "ApplicationStarted:LoadAppConfig" );
         }
 
         private  void  RegService()
         {
             //先判斷是否已經注冊過了
             //this code is called when the application stops
             Console.WriteLine( "ApplicationStarted:RegService" );
         }
         private  void  UnRegService()
         {
             //this code is called when the application stops
             Console.WriteLine( "ApplicationStopped:UnRegService" );
         }
     }
}

  

  

5、在程序根目錄運行dotnet run

 

訪問:http://localhost:51062/api/values,顯示:["Value1","Value2"]

訪問:http://localhost:51062/api/values/restart:顯示restart,再訪問http://localhost:51062/api/values正常返回["Value1","Value2"]

 

 

 

訪問:http://localhost:51062/api/values/stop,顯示:stop,再訪問http://localhost:51062/api/values就是404了

 

 

 

stop后由於netcore進程已經被關閉,沒有了http監聽,通過url方式是無法重新啟動了,這里可以借助類似supervisor的工具來停止進程,啟動進程。

 

 

三、源碼地址

 https://github.com/andrewfry/AspNetCore-App-Restart

四、其它實現

1、除了上面,還可以通過中間件的形式,實現遠程關閉

新增一個中間件的類:

復制代碼
public class RemoteStopMiddleware
    {
        private RequestDelegate _next;
        private const string RequestHeader = "Stop-Application";
        private const string ResponseHeader = "Application-Stopped";

        public RemoteStopMiddleware(RequestDelegate next)
        {
            _next = next;   
        }
    
       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 if (context.Request.Method == "HEAD" && context.Request.Headers[RequestHeader].FirstOrDefault() == "No")
            {
                context.Response.Headers.Add(ResponseHeader, "No");
                // See you on the next request.
                //Program.Shutdown();
            }
            else
           {
               await _next(context);
           }
       }
    }
復制代碼

 

2、注冊中間件

1
2
3
4
5
6
7
8
9
10
11
12
public  void  Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime lifetime)
         {
             if  (env.IsDevelopment())
             {
                 app.UseDeveloperExceptionPage();
             }
 
             app.UseMvc();
             app.UseMiddleware<RemoteStopMiddleware>();
             lifetime.ApplicationStarted.Register(OnStart); //1:應用啟動時加載配置,2:應用啟動后注冊服務中心
             lifetime.ApplicationStopped.Register(UnRegService); //應用停止后從服務中心注銷
         }

3、運行程序,用postman發起一個head請求,請求頭中加

{

Stop-Application:Yes

}

 

詳細說明可參考:https://www.cnblogs.com/artech/p/application-life-time.html

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM