.NET之Kill -15 优雅退出
背景:运维人员在每次进行代码升级版本的时候,会执行kill 命令关闭进程,再上传代码包。这时候会出现以下问题:
1. 已接收的HTTP请求业务没有处理完成就立即停止进程
如果让程序自动处理完业务后关闭进程会出现以下问题:
1. 拒绝接收新的HTTP请求消息
以下截图是本机代码测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | using D.TestKill15; using D.TestKill15.NLogsUtil; var builder = WebApplication.CreateBuilder(args); // NLog 日志 builder.Services.AddNLogUtil(); builder.Services.AddControllers(); //builder.Services.AddHealthChecks();微软的探针,查看服务是否存活 builder.WebHost.UseKestrel(o => { o.ListenAnyIP(5000); }); var app = builder.Build(); var nlog = app.Services.GetService<INLogService>(); if (args.Length > 0) { await Console.Out.WriteLineAsync($ "开始输出args参数,共{args.Length}个" ); nlog.Info($ "开始输出args参数,共{args.Length}个" ); foreach ( var arg in args) { await Console.Out.WriteLineAsync(arg); nlog.Info(arg); } } else { await Console.Out.WriteLineAsync($ "args入参长度为{args.Length}" ); nlog.Info($ "args入参长度为{args.Length}" ); } int requestCount = 0; bool isExit = false ; app.Use(async (httpContext, next) => { await Console.Out.WriteLineAsync($ "{DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss.ffff ")}-收到HTTP请求-{requestCount}" ); if (isExit) { await Console.Out.WriteLineAsync($ "{DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss.ffff ")}-已收到退出程序指令,程序正在退出,拒绝接受新消息" ); httpContext.Abort(); } else { Interlocked.Increment( ref requestCount); try { await next(); } finally { Interlocked.Decrement( ref requestCount); } } }); // 收到关闭请求 app.Lifetime.ApplicationStopping.Register(async () => { await Console.Out.WriteLineAsync($ "{DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss.ffff ")}-ApplicationStopping start" ); isExit = true ; SpinWait.SpinUntil(() => requestCount == 0); //Console.Out.WriteLineAsync($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff")}-等待{20000/1000}s后再关闭"); //Thread.Sleep(20000); 另外一种方案,延迟多少ms后,自动关闭 //Console.Out.WriteLineAsync($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff")}-等待完成,执行关闭"); }); // 执行关闭 app.Lifetime.ApplicationStopped.Register(async () => { await Console.Out.WriteLineAsync($ "{DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss.ffff ")}-ApplicationStopped start" ); }); app.MapControllers(); //app.MapHealthChecks("/healthz"); app.Run(); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | using D.TestKill15.NLogsUtil; using Microsoft.AspNetCore.Mvc; namespace D.TestKill15 { [Route( "api/[controller]" )] [ApiController] public class TestController : ControllerBase { INLogService _nLogService; public TestController(INLogService nLogService) { _nLogService = nLogService; } [HttpGet( "get" )] public async Task< string > Get( int ? delayTime) { var t = $ "{DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss.ffff ")}-收到消息" ; _nLogService.Info(t); await Console.Out.WriteLineAsync(t); if (delayTime != null ) { var s = $ "{DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss.ffff ")}-开始执行函数需要耗费{delayTime}ms" ; _nLogService.Info(s); await Console.Out.WriteLineAsync(s); await Task.Delay(delayTime.Value); var e = $ "{DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss.ffff ")}-函数执行{delayTime}ms完毕" ; _nLogService.Info(e); await Console.Out.WriteLineAsync(e); } var r = $ "返回消息:{DateTime.Now.ToString(" yyyy-MM-dd HH:mm:ss.ffff ")}" ; await Console.Out.WriteLineAsync(r); return r; } } } |
彪悍的人生不需要解释,彪悍的代码不需要注释。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
2020-04-21 VSCode_操作
2018-04-21 http协议