惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
J
Java Code Geeks
Martin Fowler
Martin Fowler
宝玉的分享
宝玉的分享
V
Visual Studio Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
M
MIT News - Artificial intelligence
U
Unit 42
博客园 - 三生石上(FineUI控件)
博客园 - 聂微东
The GitHub Blog
The GitHub Blog
I
InfoQ
WordPress大学
WordPress大学
H
Help Net Security
D
Docker
B
Blog
腾讯CDC
A
About on SuperTechFans
Recent Announcements
Recent Announcements
雷峰网
雷峰网
有赞技术团队
有赞技术团队
C
Check Point Blog
Y
Y Combinator Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC

博客园 - 彪悍的代码不需要注释

AI编写的离线压测工具 虚拟机ftp安装 openclaw本地安装 Redhat服务器离线安装FTP 使用python脚本提取SVN近10年提交记录 本地VMware Workstation Pro的rhel-server-7.9-x86_64服务器配置本地源 敏感词过滤 限流 幂等性 Windows本地生成SSL证书,用于本地调试 【转】大文件上传原理及C#实现方案 【转】C# 实现接口幂等性的四种方案 WPF创建不规则窗体时WebBrowser控件不显示的问题 QrCode 排查java代码慢-arthas工具 针对clickonce发布后的程序,优化处理省略弹出层 赔率 winform发布ClickOnce到Linux服务器 CentOS obs直播RTMP协议推流到Nginx流媒体服务器到VUE使用HLS直播
.NET之Kill -15 优雅退出
彪悍的代码不需要注释 · 2024-04-21 · via 博客园 - 彪悍的代码不需要注释

背景:运维人员在每次进行代码升级版本的时候,会执行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;
        }
    }
}