Asp.NetCore远程自启动、重启、关闭实现

1、背景

NetCore做为微服务能够注册到服务中心,服务中心能够远程启动、重启、关闭该微服务html

 

2、实现

一、建立一个NetCore 2.0 WebApi项目git

二、建立一个进程去管理NetCore程序进程github

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;
        }
    }

  三、把ApplicationManager加入到Main中web

public static void Main(string[] args)
        {
            try
            {
                var appManager = ApplicationManager.Load();

                do
                {
                    appManager.Start();
                } while (appManager.Restarting);


            }
            catch (Exception ex)
            {

            }
        }

  四、在程序的ValuesController中实现重启、关闭的Apiapi

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)
        {
        }
    }
}

六、给程序启动和中止加入日志标签app

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");
        }
    }
}

  

  

五、在程序根目录运行dotnet runasync

 

访问: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了post

 

 

 

stop后因为netcore进程已经被关闭,没有了http监听,经过url方式是没法从新启动了,这里能够借助相似supervisor的工具来中止进程,启动进程。

 

 

3、源码地址

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

4、其它实现

一、除了上面,还能够经过中间件的形式,实现远程关闭

新增一个中间件的类:

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);
           }
       }
    }

 

二、注册中间件

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);//应用中止后从服务中心注销
        }

三、运行程序,用postman发起一个head请求,请求头中加

{

Stop-Application:Yes

}

 

详细说明可参考:https://www.cnblogs.com/artech/p/application-life-time.html

相关文章
相关标签/搜索