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