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

相關文章
相關標籤/搜索