You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core 3.1程序在Systemd服务中执行HTTP请求时冻结问题求助

解决.NET Core程序在Systemd下HTTP请求冻结的问题

我之前碰到过类似的场景,结合你的描述,程序在CLI运行正常但Systemd下HTTP请求卡住,大概率是网络环境差异或者**.NET异步/Handler配置**的问题,下面是一步步的排查和解决方法:

1. 先捕获异常,明确问题根源

当前代码没有异常捕获,冻结后看不到任何错误信息,第一步要先把问题具体化。修改代码添加异常处理和超时设置:

//Systemd - Bug hunting
Console.WriteLine("starting download..");
try
{
    var c = new HttpClient { Timeout = TimeSpan.FromSeconds(8) }; // 添加超时,避免无限等待
    var _download = await c.GetStringAsync("https://www.google.com");
    Console.WriteLine($"Downloaded {_download.Length} characters.");
}
catch (Exception ex)
{
    Console.WriteLine($"Download failed: {ex.Message}");
    Console.WriteLine($"Stack trace: {ex.StackTrace}");
    // 处理聚合异常,展开内部错误
    if (ex is AggregateException aggEx)
    {
        foreach (var innerEx in aggEx.InnerExceptions)
        {
            Console.WriteLine($"Inner exception: {innerEx.Message}");
        }
    }
}
//--------------------- 

重新部署后,通过journalctl -u mydaemon.service查看日志,就能知道是DNS解析失败、连接超时还是其他具体问题。

2. 排查Systemd服务的网络环境

CLI和Systemd的运行环境存在差异,重点检查这两点:

  • 用户网络权限:切换到myuser用户,执行curl https://www.google.com,看是否能正常获取内容。如果不行,检查该用户的网络访问权限(比如防火墙规则、SELinux配置)。
  • DNS解析问题:Systemd默认使用systemd-resolved做DNS解析,可能和CLI的DNS配置不一致。可以临时修改服务配置添加DNS测试:
    修改ExecStart为:
    ExecStart=/bin/sh -c "nslookup www.google.com && /usr/bin/dotnet /home/myuser/applicationDir/mydaemon.dll"
    
    重启服务后查看journalctl输出,如果nslookup失败,说明DNS配置有问题,需要检查/etc/resolv.conf或systemd-resolved的运行状态。

3. 切换HttpClient的Handler(解决SocketsHttpHandler兼容性问题)

.NET Core 3.1默认使用SocketsHttpHandler,这个Handler在部分Linux环境下存在兼容性问题,会导致请求卡住。可以强制切换回旧的HttpClientHandler:

方法一:代码中指定Handler

var handler = new HttpClientHandler();
var c = new HttpClient(handler) { Timeout = TimeSpan.FromSeconds(8) };

方法二:通过环境变量全局切换

在mydaemon.service的[Service]段添加:

Environment=DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER=0

执行systemctl daemon-reload和systemctl restart mydaemon.service使配置生效。

4. 检查Systemd服务配置细节

  • ServiceType设置:如果你的程序是长期运行的守护进程,建议设置Type=notify(需要程序支持发送就绪通知),或者确保Type=simple下主线程不会提前退出。如果主线程启动后台线程后就退出,整个进程会被终止,但你的情况是冻结,这个可能性较低,但可以检查下程序主线程的逻辑。
  • 环境变量一致性:对比CLI下的环境变量(执行printenv)和Systemd服务的环境变量,确保关键变量(比如HTTP_PROXY、PATH)一致,可在[Service]段添加缺失的环境变量。

5. 调整超时和重启逻辑

如果请求确实是超时,你可以根据实际情况调整HttpClient的超时时间,同时检查Systemd的Restart配置。比如把超时设为5秒,这样请求失败后会立刻抛出异常,你能在日志里看到错误,而不是等着Systemd触发重启。

按照上面的步骤排查,一般就能找到问题所在。我之前碰到的情况是SocketsHttpHandler在CentOS 7下的DNS解析异常,切换回旧Handler就解决了。

内容的提问来源于stack exchange,提问作者Kevin Mueller

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 11:28:17