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


一、背景

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

 

二、實現

1、創建一個NetCore 2.0 WebApi項目

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

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中

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

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


            }
            catch (Exception ex)
            {

            }
        }

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

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、給程序啟動和停止加入日志標簽

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、注冊中間件

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