背景:運維人員在每次進行代碼升級版本的時候,會執行kill 命令關閉進程,再上傳代碼包。這時候會出現以下問題:
1. 已接收的HTTP請求業務沒有處理完成就立即停止進程
如果讓程序自動處理完業務後關閉進程會出現以下問題:
1. 拒絕接收新的HTTP請求消息
以下截圖是本機代碼測試:
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();
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; } } }