前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >福爆 | 博客升级 .NET Core 3.0 又踩一坑

福爆 | 博客升级 .NET Core 3.0 又踩一坑

作者头像
Edi Wang
发布2019-09-29 16:23:41
1.2K0
发布2019-09-29 16:23:41
举报
文章被收录于专栏:汪宇杰博客

导语

昨天刚发了一篇《与时俱进 | 博客现已运行在 .NET Core 3.0 及 Azure 上》得瑟,本以为踩完了坑,结果晚上博客又爆了。Azure Application Insights 监控里发现了大量异常。我们来看看我如何收取福爆。

生产大爆炸

发生问题的是已经被删除的博客文章,正常情况下,这些不存在的文章会直接显示自定义的404页面,但实际上产生了500异常。日志如下:

2019-09-26 00:11:50.8405|RD00155DB89A5B|WARN|Moonglade.Web.Controllers.PostController|Post not found, parameter '2014/7/23/my-surface-pro-3-review-system-software'.,GET https://edi.wang/post/2014/7/23/my-surface-pro-3-review-system-software,Slug,66.249.71.135

2019-09-26 00:11:51.1174|RD00155DB89A5B|WARN|Moonglade.Web.Controllers.PostController|Post not found, parameter '2014/7/23/my-surface-pro-3-review-system-software'.,GET https://edi.wang/error,Slug,66.249.71.135

2019-09-26 00:11:51.1174|RD00155DB89A5B|ERROR|Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware|An unhandled exception has occurred while executing the request.,System.ArgumentException: An item with the same key has already been added. Key: x-pingback

at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)

at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)

at Microsoft.AspNetCore.HttpSys.Internal.HeaderCollection.Add(String key, StringValues value)

看上去像是个Pingback HTTP头被重复添加的问题。但实际上这个头被添加产生异常的本质原因是请求博客文章的Slug这个Action被执行了两次

重现故障

这个问题在开发时并没有发现,staging环境可以重现,但由于偷懒,没测过exception path,happy path过了就发布了。之所以开发环境 works on my machine 是因为这样一个设定,大部分 ASP.NET Core 程序都会这么做,毕竟是默认模板里的实践:

if (env.IsDevelopment())

{

ListAllRegisteredServices(app);

app.UseDeveloperExceptionPage();

}

else

{

app.UseExceptionHandler("/error");

app.UseStatusCodePagesWithReExecute("/error", "?statusCode={0}");

}

出问题的是 UseStatusCodePagesWithReExecute() 这个中间件。

最终在 GitHub 上找到了一个已知问题:

https://github.com/aspnet/AspNetCore/issues/13715

我用 VS2019 16.3.1 + .NET Core 3.0 正式版建了个测试工程,重现了这个问题。

public IActionResult Index(int id = 0)

{

if (id == 1)

{

return NotFound();

}

return View();

}

[Route("/error")]

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]

public IActionResult Error(int? statusCode = null)

{

return Content($"Test Error Action: {statusCode}");

}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

{

//app.UseStatusCodePages();

//app.UseExceptionHandler("/error");

app.UseStatusCodePagesWithReExecute("/error", "?statusCode={0}");

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.UseEndpoints(endpoints =>

{

endpoints.MapControllerRoute(

name: "default",

pattern: "{controller=Home}/{action=Index}/{id?}");

});

}

访问 /Home/Index?id=1

id=1的请求成功执行到 NotFound(); 正常情况应该立即执行 /error?statusCode=404,当实际上 Error 这个 Action 根本没有跑进去,而是马上再次执行了 Index,id=0

而因为执行的逻辑是ReExecute,也就是把action的执行结果放到“父”action里输出,所以会触发两次pingback头的添加,导致我博客大爆炸。

复制粘贴 能跑就行

微软并不打算在 3.0 的补丁更新中修复这个问题,而是直接放到了 3.1。好在微软提供了 workaround,所以我们只能先忍几个月。

在 UseRouting() 和 UseStatusCodePagesWithReExecute() 之间加入一段神奇的代码,即可结束福爆。

app.UseStatusCodePagesWithReExecute("/error", "?statusCode={0}");

// Workaround .NET Core 3.0 known bug

// https://github.com/aspnet/AspNetCore/issues/13715

app.Use((context, next) => {

context.SetEndpoint(null);

return next();

});

实在不行 删库跑路 也挺省心

目前 .NET Core 3.0 升级问题多多,资料少少,一不小心就容易领取福报。如果追求刺激和拥抱开源的乐趣,可以像我或者博客园一样直接踩坑。如果追求稳定,不想被公司开除,建议等 3.1 再更新吧~ 毕竟微软拥抱开源以后的产品,.1 才是能用的(早上更新的 VS2019 16.3.1笑而不语)。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 汪宇杰博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
消息队列 TDMQ
消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档