Newtonsoft.Json在Azure Web App Service中序列化性能异常缓慢问题求助
针对你遇到的本地与Azure环境序列化性能差异巨大的问题,我整理了几个优先级较高的排查和优化方向,你可以逐一尝试:
1. 优化自定义JsonNaNConverter的性能
你的自定义转换器会处理对象中所有double/float类型的值,当对象规模较大时,转换器的性能开销会被放大。原代码中的类型判断逻辑可以简化——因为CanConvert已经确保了输入类型,无需多次使用as进行可空类型转换:
public class JsonNaNConverter : JsonConverter { public override bool CanRead => false; public override bool CanWrite => true; public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { double val = value switch { float f => f, double d => d, _ => (double)value // 针对double?的情况,CanConvert已确保类型安全 }; if (double.IsNaN(val) || double.IsInfinity(val)) { writer.WriteNull(); return; } writer.WriteValue(val); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { throw new NotImplementedException(); } public override bool CanConvert(Type objectType) { return objectType == typeof(double) || objectType == typeof(double?) || objectType == typeof(float); } }
这种写法减少了不必要的类型转换和可空类型判断,能有效降低单值处理的开销。
2. 升级Newtonsoft.Json版本
你当前使用的12.0.1版本是2018年的旧版本,后续的13.x系列针对大对象序列化、内存分配做了大量性能优化。建议升级到最新的稳定版(目前是13.0.3),很多用户反馈升级后大对象序列化性能有显著提升。
3. 检查Azure App Service的运行平台位数
默认情况下,部分Azure App Service计划可能会以32位模式运行。对于处理3MB级别的JSON字符串,32位进程的内存压力更大,GC暂停时间会更长。你可以在Azure Portal中:
- 进入你的App Service → 配置 → 常规设置
- 将“平台”从“32位”切换为“64位”,保存后重启应用
4. 避免直接生成大字符串,改用流式序列化
直接调用JsonConvert.SerializeObject会在内存中生成完整的3MB字符串,这会触发多次GC,在Azure环境中可能因为内存碎片导致性能下降。改用流式序列化的方式可以减少内存分配:
#if WRITE_TIMER_LOGS var swSerializeTime = new System.Diagnostics.Stopwatch(); swSerializeTime.Start(); #endif using (var stringWriter = new StringWriter()) using (var jsonWriter = new JsonTextWriter(stringWriter)) { var serializer = JsonSerializer.Create(serializerSettings); serializer.Serialize(jsonWriter, responses); jsonString = stringWriter.ToString(); } #if WRITE_TIMER_LOGS swSerializeTime.Stop(); #endif
如果你的场景是直接输出到HTTP响应,还可以直接序列化到Response.OutputStream,完全避免生成大字符串。
5. 排查Azure环境的资源瓶颈
虽然你使用的是P2V2计划,但仍需确认是否存在资源限制:
- 在Azure Portal的App Service → 指标中,查看CPU使用率、内存使用率,如果CPU持续接近100%,可能存在资源节流
- 启用Application Insights的性能分析,查看序列化过程中的GC暂停时间、JIT编译耗时,定位具体的性能瓶颈
6. 确认编译和部署模式
确保你的应用是用Release模式编译的,并且部署到Azure时没有启用调试模式(Web.config中的debug属性应为false)。调试模式会禁用JIT优化,导致性能大幅下降。
内容的提问来源于stack exchange,提问作者Nick Beis

