一、背景

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

Asp.NetCore远程自启动、重启、关闭实现的更多相关文章

  1. powershell 远程重启/关闭服务器

    powershell 远程重启/关闭服务器 #启动winrm PS C:\Windows\system32> winrm quickconfig -q #设置信任主机 PS C:\Windows ...

  2. Asp.NetCore程序发布到CentOs(含安装部署netcore)--最佳实践(一)

    环境 本地 win7 服务器:Virtual Box 上的Centos ssh工具: Xshell 文件传输: xftp 1.在本地创建asp.net core应用发布 1.1 使用Vs2017 新建 ...

  3. Asp.NetCore程序发布到CentOs(含安装部署netcore)--最佳实践

    原文:Asp.NetCore程序发布到CentOs(含安装部署netcore)--最佳实践 环境 本地 win7 服务器:Virtual Box 上的Centos ssh工具: Xshell 文件传输 ...

  4. oracle 配置 自启动 和 关闭

    今天在看oracle自启动脚本,突然有点时间,总结一下!!! 第一次写博客,大家随便看看就好,有错误麻烦提醒下,不喜欢别喷,主要是锻炼自己,形成写博客的好习惯. 刚毕业,现在还没转正,在干运维和自学d ...

  5. Asp.NetCore轻松学-使用Supervisor进行托管部署

    前言 上一篇文章 Asp.NetCore轻松学-部署到 Linux 进行托管 介绍了如何在 Centos 上部署自托管的 .NET Core 应用程序,接下来的内容就是介绍如何使用第三方任务管理程序来 ...

  6. Asp.NetCore程序发布到CentOs(含安装部署netcore)--最佳实践(二)

    Asp.NetCore程序发布到CentOs(含安装部署netcore)--最佳实践(一) 接上一篇 3. Nginx配置反向代理 3.1 cnetos 安装nginx 首先,我们需要在服务器上安装N ...

  7. 使用PowerShell自动部署ASP.NetCore程序到IIS

    Windows PowerShell 是一种命令行外壳程序和脚本环境,使命令行用户和脚本编写者可以利用 .NET Framework的强大功能.有关于更多PowerShell的信息,可参阅百度词条 接 ...

  8. Asp.Net 远程连接Oracle数据库

    Asp.Net 远程连接Oracle数据库 首先从微软停止.Net FrameWork支持Oracle数据库的研发,转为第三方提供说起,微软是很有实力的公司,他在桌面领域令其他对手望其项背,产品战线也 ...

  9. ASP.NETCore使用AutoFac依赖注入

    原文:ASP.NETCore使用AutoFac依赖注入 实现代码 1.新建接口类:IRepository.cs,规范各个操作类的都有那些方法,方便管理. using System; using Sys ...

随机推荐

  1. Prism5.0新内容 What's New in Prism Library 5.0 for WPF(英汉对照版)

    Prism 5.0 includes guidance in several new areas, resulting in new code in the Prism Library for WPF ...

  2. Elasticsearch 文档专用

    ES安装等操作 http://blog.csdn.net/cnweike/article/details/33736429 https://www.elastic.co/guide/cn/elasti ...

  3. request.setAttribute("username", username);//一定要保存,OGNL才能获取${username}

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, ...

  4. 持久层框架:MyBatis 3.2(1)

    MyBatis 的前身就是 iBatis .是一个数据持久层(ORM)框架. iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架.iBATIS提供的持久 ...

  5. BAT级别对照表

  6. [置顶] C语言学习入门

    编译文件:cc -c one.c two.c  生成.o目标文件 链接文件:cc one.o two.o     默认生成 a.out 执行文件 指定生成的可执行文件名   cc -o one one ...

  7. 打造属于自己的安卓menu

    首先,我们来看看这张图吧 看下面的menu菜单,是原装的菜单,好丑陋哦,类似于小编这么爱美的人来说,纯粹就是天大的打击,接受不起.于是,小编就发奋图强,努力,努力,再努力,终于,将菜单改的漂亮了一点, ...

  8. Java中最常见的十道面试题

    第一,谈谈final, finally, finalize的区别. final?修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为 ...

  9. LEX下出毛病的问题

    毛病! 1.今日写词法分析,回想起第一次写时候的蓝色警告:不要随便管理员.so,便Win+R,"cmd",回车. 2.在用lex写的时候,注意注释是 /*注释放于此处*/ 而非一般 ...

  10. 原生js面向对象写法

    Mouse就是一个类,有自己的成员变量和成员方法,成员方法一定加上prototype,避免js原型的坑. var Mouse = function(id) { this.id = id; this.n ...