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

.NET Core 3.1接收大JSON请求触发OutOfMemoryException如何修复

异常根因

该OutOfMemoryException由ASP.NET Core默认的请求处理逻辑触发:默认System.Text.Json输入格式化器会将完整1.21GB请求体全部加载到内存后再执行反序列化,你的JSON结构中仅包含base64编码的二进制内容,base64本身比原始二进制大33%,反序列化时还需要额外分配字节数组存储解码后的内容,单请求内存峰值会超过2GB,超过Kubernetes Pod配置的内存阈值后就会触发OOM。

可行修复方案

1. 跳过默认模型绑定,流式处理请求体

默认BodyModelBinder会自动缓冲全量请求体,你可以关闭自动绑定,直接从Request.Body流逐块解析数据,避免一次性加载全量内容:

[HttpPost]
[DisableRequestSizeLimit] // 可按需替换为指定大小的[RequestSizeLimit]
public async Task<IActionResult> ProcessLargePayload()
{
    // 关闭Kestrel默认的全量请求缓冲,仅缓冲超出阈值的部分到磁盘
    Request.EnableBuffering(bufferThreshold: 1024 * 1024, bufferLimit: null);

    // 流式解析JSON,不加载全量内容到内存
    using var jsonDoc = await JsonDocument.ParseAsync(Request.Body, new JsonDocumentOptions
    {
        MaxDepth = 4,
        AllowTrailingCommas = false
    });

    if (jsonDoc.RootElement.TryGetProperty("base64", out var base64Prop))
    {
        // 直接读取base64内容为流,不要调用GetString()加载全量字符串
        using var base64Stream = base64Prop.GetStreamFromBase64();
        // 直接将流写入目标存储(文件/对象存储/数据库等),无需在内存驻留全量数据
        using var targetStream = File.Create("output_binary.dat");
        await base64Stream.CopyToAsync(targetStream, bufferSize: 128 * 1024);
    }

    return Ok();
}

注:GetStreamFromBase64方法需要.NET 5及以上版本支持,低版本可自行实现base64逐块解码逻辑

2. 调整服务端配置

在Program.cs中修改Kestrel和JSON序列化的默认配置,适配大请求场景:

// 配置Kestrel最大请求体大小
builder.WebHost.ConfigureKestrel(opt =>
{
    opt.Limits.MaxRequestBodySize = 2 * 1024 * 1024 * 1024L; // 设为2GB,可按需调整
});

// 调整JSON序列化选项降低内存占用
builder.Services.AddControllers()
    .AddJsonOptions(opt =>
    {
        opt.JsonSerializerOptions.MaxDepth = 4;
        opt.JsonSerializerOptions.DefaultBufferSize = 128 * 1024;
    });

3. 调整Kubernetes资源配置

提高Pod的内存配额,避免被K8s OOM Killer主动杀掉:

resources:
  requests:
    memory: "2Gi"
    cpu: "1"
  limits:
    memory: "4Gi"
    cpu: "2"

建议将Pod配置为Guaranteed QoS等级(requests和limits值完全一致),降低集群资源紧张时Pod被优先回收的概率。

4. 长期架构优化

如果业务允许,优先修改交互协议:不要用JSON承载超大二进制内容,改为调用方直接将二进制流上传到对象存储(如MinIO、阿里云OSS等),仅将存储地址回调给你的API,从根本上避免大请求体带来的性能和稳定性问题。如果必须用JSON传输,也可以改为分块上传,单分片大小控制在100MB以内,后端完成分片拼接。

内容的提问来源于stack exchange,提问作者Lalit Rajput

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 23:00:00