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
阿里云: www.aliyun.com
华赐软件: www.huacisoft.com
C#开源社区: www.opencsharp.net
清泓美肤苑: 清泓美肤苑
bootstrap权限管理系统: Asp.Net Mvc3 bootstrap权限管理系统

浙公网安备 33010602011771号