非常抱歉,10:00~10:30 左右博客站点出现故障,给您带来麻烦了,请您谅解。

故障原因与博文中谈到的部署变更有关,但背后的问题变得非常复杂,复杂到我们都在怀疑与阿里云服务器 CPU 特性有关。

这篇博文本来准备 9:30 左右发布的,但发布博文时出现了 docker swarm 部署异常情况,切换到 docker-compose 部署后问题依旧,一直到 10:30 左右才恢复正常,继续发布这篇博文,在标题中加上了“翻车记”。

原先的博文正文开始:

周一向大家汇报车况之后,我们的 .NET Core 新车继续以 docker-compose 手动挡的驾驶方式行驶在信息高速公路上,即使昨天驶上了更快的高速(并发量更大的访问高峰),也没有翻车。经过这周3天访问高峰的考验,我们终于可以充满信心地宣布——我们度过了新车上路最艰难的磨合期,开新车的剧情从“翻车记”进入到了“行车记”。

翻车成为历史,行车正在进行时,但离我们的目标“飙车”还有很长的一段距离,“行车记”更多的是修车记,新车改造记。

目前这辆 .NET Core 新车有2个重大问题,一是油耗高(CPU消耗高),有时还会断油(CPU 100% 造成 502),二是手动挡驾驶实在太累。

针对油耗高问题,这两天我们从节能降耗角度对博客系统的 C# 代码进行了优化。

从日志中发现,有些特别长的 url 会造成 ASP.NET Core 内置的 url rewrite 中间件在正则处理时执行超时。

System.Text.RegularExpressions.RegexMatchTimeoutException: The RegEx engine has timed out while trying to match a pattern to an input string. This can occur for many reasons, including very large inputs or excessive backtracking caused by nested quantifiers, back-references and other factors.at System.Text.RegularExpressions.RegexRunner.DoCheckTimeout()at Go64(RegexRunner )at System.Text.RegularExpressions.RegexRunner.Scan(Regex regex, String text, Int32 textbeg, Int32 textend, Int32 textstart, Int32 prevlen, Boolean quick, TimeSpan timeout)at System.Text.RegularExpressions.Regex.Run(Boolean quick, Int32 prevlen, String input, Int32 beginning, Int32 length, Int32 startat)at System.Text.RegularExpressions.Regex.Match(String input, Int32 startat)at Microsoft.AspNetCore.Rewrite.UrlMatches.RegexMatch.Evaluate(String pattern, RewriteContext context)at Microsoft.AspNetCore.Rewrite.IISUrlRewrite.IISUrlRewriteRule.ApplyRule(RewriteContext context)at Microsoft.AspNetCore.Rewrite.RewriteMiddleware.Invoke(HttpContext context)

对于这个问题,我们采取的节能降耗措施是借助 AspNetCore.Rewrite 的机制检查 url 的长度,对超出长度限制的 url 直接返回 400 状态码。

public class UrlLengthLimitRule : IRule
{private readonly int _maxLength;private readonly int _statusCode;public UrlLengthLimitRule(int maxLength, int statusCode){_maxLength = maxLength;_statusCode = statusCode;}public void ApplyRule(RewriteContext context){var url = context.HttpContext.Request.GetDisplayUrl();if (url.Length > _maxLength){context.HttpContext.Response.StatusCode = _statusCode;context.Result = RuleResult.EndResponse;context.Logger.LogWarning($"The Url is too long to proceed(length: {url.Length}): {url}");}}
}

为了节约每次请求时创建 DbContext 的开销,重新启用了 DbContextPool ,从省吃俭用的角度进一步降低油耗。

services.AddDbContextPool<CnblogsDbContext>(options =>
{options.UseSqlServer(Configuration.GetConnectionString("BlogDb"), builder =>{builder.UseRowNumberForPaging();builder.EnableRetryOnFailure(maxRetryCount: 3,maxRetryDelay: TimeSpan.FromSeconds(10),errorNumbersToAdd: new int[] { 2 });});options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
});

限制了一个耗油大户,有些字符数特别多的博文内容(比如将图片以 base64string 保存在博文内容中)在正则处理时特别消耗 CPU ,而且 memcached 无法缓存(以后会改用 redis 缓存解决这个问题),对这些博文采取了限制措施。这是我们在迁移时自己给自己挖的坑,旧版中已经采取了措施,但在迁移时遗漏了。

另一个节能降耗措施同样是针对博文内容,将从数据库中获取博文内容的代码由 EF Core + LINQ 改为 Dapper + 存储过程,以避开 好大一个坑: EF Core 异步读取大字符串字段比同步慢100多倍 。在执行 DbCommand.ExecuteReaderAsync 时,EF Core 使用的是 CommandBehavior.Default ,Dapper 使用的是 CommandBehavior.SequentialAccess 。在有些场景下使用 CommandBehavior.Default 查询很大的字符串,有严重的性能问题,不仅查询速度极慢,而且很耗 CPU (也有可能与使用的 SQL Server 版本有关),只要使用 EF Core ,就只能使用 CommandBehavior.Default ,EF Core 没有提供任何修改 CommandBehavior 的配置能力,所以换成 Dapper 也是无奈之举。

public async Task<string> GetByPostIdAsync(int postId)
{using (var conn = new SqlConnection(GlobalSettings.PostBodyConnectionString)){return await conn.QueryFirstOrDefaultAsync<string>("[dbo].[Cnblogs_PostBody_Get]",new { postId },commandType: CommandType.StoredProcedure);}
}

对于手动挡驾驶太累问题,在这次改造过程中,我们采取一个被全园人都反对的举措,没有安装众星捧月的 k8s 高档自动驾驶系统,而是安装了小众的 docker swam 中档自动驾驶系统。这种“docker swarm 虐我千百遍,我待 docker swarm 如初恋”的情有独钟的傻劲,也许是受《try everything》这首歌的影响,我们还是想试试在优化后是否可以使用 docker swarm 自动驾驶系统在高速上正常开车(抗住访问高峰),先看看 docker swarm 究竟是弱不禁风,还是只是娇生惯养?

为了照顾 docker swarm 的娇生惯养,我们在代码中减少一处额外的 HttpClient 造成的 socket 连接开销。在新版博客系统中为了防止有些地方在迁移时遗漏了,我们在一个 middleware 中会跟踪所有 404 响应,并用 404 对应的 url 向旧版博客发请求,如果旧版响应是 200 ,就记录的日志中留待排查。在访问高峰,大量的 404 请求也会带来不少的 socket 连接开销。

Docker swarm 部署的 .NET Core 博客站点昨天晚上就已经上线观察了,但昨天是 docker swarm 与 docker-compose 混合部署,今天一大早已经全部换成 docker swarm 部署了,新车以由手动挡驾驶模式切换为 docker swarm 自动驾驶模式行驶,目前一切状况良好(9:10左右),就看今天上高速的情况了。

我们准备了备案,假如 docker swam 在访问高峰撑不住,随时可以切换到手动挡(docker-compose 部署随地待命)。

-----原先的博文正文结束-----

9:30 左右,刚准备发这篇博文时发现还没上高速才刚上快速路 docker swarm 就有点撑不住了(3台8核16G的阿里云服务器),赶紧向手动挡切换,立即向负载均衡添加了3台4核8G的 docker-compose 部署的阿里云服务器(这3台在向手动挡切换前就一直处于运行状态),6台服务器撑住了。

根据当时的情况,我们完全认为就是 docker swarm 的问题,是 docker swarm 弱不禁风,docker swarm 是一个低档的自动驾驶系统,无法用它在高速上开车(现在来看不一定是 docker swarm 的问题)。于是,我们进行进一步的切换,将处于关机状态的另外4台 docker-compose 部署的服务器开起来加入负载均衡,将 docker swarm 的服务器摘下负载均衡并关机,这时负载均衡中有7台4核8G的 docker-compose 部署的服务器,按照前几天的情况看,完全可以撑住。但是,万万没有想到,从 10:00 左右开始,这7台竟然也撑不住,而且问题表现与之前 docker swarm 遇到的问题一样,部分服务器本机请求时快时慢,快的时候在10毫秒左右,慢的时候请求执行时间超过30秒,甚至超时。赶紧继续加服务器,但这时加服务器需要购买、启动、预热,虽然是脚本自动完成的,但也比较慢,加了服务器后,问题依旧,于是将一些出问题的服务器下线,但会有其他服务器又出现这个问题,即使新加的服务器也会出现这个问题,在一边加服务器一边将出问题的服务器下线的同时,将 docker swarm 集群的3台服务器也启动起来加入集群分担压力,但很快 docker swarm 集群中的部分服务器也出现了同样的问题。。。

10:30 左右,当达到某种我们所不知道的平衡点时,立即风平浪静,一切都回归正常,所有服务器本机器本机请求都飞快,包含 docker swarm 集群中的服务器。

现在问题变得格外复杂,回想之前的翻车与正常行驶的情况,从直觉判断中似乎感觉到了一点点新的蛛丝马迹,一个我们从没怀疑的点可能要纳入考虑范围 —— 阿里云服务器 CPU 的性格特点。接下来,我们会仔细分析一下,看能不能找到一点规律,按照比较符合阿里云服务器 CPU 性格特点的方式接入负载,看是否可以避开这个问题。

再次抱歉,给大家带来这么大的麻烦,请谅解。这次故障我们万万没有想到,高速开车比我们想象的难很多,即使同样的部署,接入负载或者增加服务器的时间点不一样,也会有不一样的表现。

Powered by .NET Core 系列博文:

  • 【故障公告】发布 .NET Core 版博客站点引起大量 500 错误
  • 【网站公告】.NET Core 版博客站点第二次发布尝试
  • 暴风雨中的 online : .NET Core 版博客站点遭遇的高并发问题进展
  • Powered by .NET Core 进展:验证高并发性能问题嫌疑犯 docker swarm
  • 同“窗”的较量:部署在 Windows 上的 .NET Core 版博客站点发布上线
  • 做梦也没有想到:Windows 上的 .NET Core 版博客系统表现更糟糕
  • 峰回路转:去掉 DbContextPool 后 Windows 上的 .NET Core 版博客表现出色
  • Powered by .NET Core 进展0815:第5次发布尝试(Windows部署)
  • 高速开车换底盘记:Windows 与 Linux 部署都抗住了,但修车任务艰巨
  • Powered by .NET Core 进展0819:高速开车车况汇报

园友相关博文:

  • 博客园升级有感一点建议
  • 博客园翻车启示录
  • 生产环境(基于docker)故障排除? 有感于博客园三番五次翻车
  • 博客园在升级的路上,不妨更自信些,同时说说我们可以为博客园做些什么

转载于:https://www.cnblogs.com/cmt/p/11391410.html

行车记+翻车记:.NET Core 新车改造,C# 节能降耗,docker swarm 重回赛道相关推荐

  1. 记一次.Net Core通过GDI+在CentOS 7(Docker)环境中绘图报错The type initializer for ‘Gdip‘ threw an exception的问题及处理方式

    今天在Docker环境布置项目,在登录页面中有一个功能就是需要后端动态绘制一个验证码图片,防止前端通过机器或爬虫工具模拟自动登录. 在开发机器上(windows10)调试正常,但是部署到centos7 ...

  2. 索尼rx1r人脸识别_一波三折的闲鱼翻车记——索尼RX1R入手记录

    一波三折的闲鱼翻车记--索尼RX1R入手记录 2019-03-03 11:38:08 45点赞 63收藏 170评论 在我手边没有任何摄影设备的时候,我想,假如我能有个拍照手机来记录日常生活就好了·· ...

  3. 闲鱼下单时显示服务器繁忙,闲鱼翻车记。闲鱼用验机报告需要注意的问题,否则分分钟被水鱼...

    闲鱼翻车记.闲鱼用验机报告需要注意的问题,否则分分钟被水鱼 2019-10-03 21:35:34 62点赞 75收藏 163评论 本文主要想说的:闲鱼验机报告觉得不合适,一定要拒绝本次交易.对自己有 ...

  4. 记一次.Net Core程序启动失败的排查过程

    阅文时长 | 2分钟 字数统计 | 3212字符 主要内容 | 1.引言&背景 2.排查.NetCore启动失败详细过程 3.声明与参考资料 『记一次.Net Core程序启动失败的排查过程』 ...

  5. 记一次企业级爬虫系统升级改造(四):爬取微信公众号文章(通过搜狗与新榜等第三方平台)

    首先表示抱歉,年底大家都懂的,又涉及SupportYun系统V1.0上线.故而第四篇文章来的有点晚了些~~~对关注的朋友说声sorry! SupportYun系统当前一览: 首先说一下,文章的进度一直 ...

  6. 记一次企业级爬虫系统升级改造(四):爬取微信公众号文章(通过搜狗与新榜等第三方平台)...

    首先表示抱歉,年底大家都懂的,又涉及SupportYun系统V1.0上线.故而第四篇文章来的有点晚了些~~~对关注的朋友说声sorry! SupportYun系统当前一览: 首先说一下,文章的进度一直 ...

  7. html计时器记 天数,手机如何记天数 记天数软件有哪些

    在生活中,有很多时候我们都需要记时间记天数,虽然一个两个我们还可以接受,但是要是我们记得数量比较多的时候那就难了,而且也很容易记错.本文就将为大家整理手机如何使用软件记天数. 如何使用手机软件记天数 ...

  8. .Net Core通过NPOI在CentOS 7(Docker)环境中导出Excel报错The type initializer for ‘Gdip‘ 的问题

    一.前言 今天在AspNetCore5.0环境中做了一个导出Excel的功能,在开发机器上(windows10)调试正常,但是部署到centos7容器(容器基础环境mcr.microsoft.com/ ...

  9. ZJOI2019一试翻车记

    前言 退役了 day1 day1上午是lyx的讲课 标题是<具体数学> 从上升幂.下降幂到斯特林数的求一行.一列.单个之类的 然后还有熟悉的猪叫 day1下午是kcz的杂题选讲 不知为何, ...

最新文章

  1. sql嵌套查询返回多个字段_list4 SQL复杂查询
  2. 华为手机安装系统能换鸿蒙,华为鸿蒙将全面上线,安卓系统或将被彻底替换
  3. 常见的14种异常心电图的波形特点
  4. python twisted教程 三–开始twisted
  5. H.264的编解码流程
  6. 作用域链涉及了什么计算机底层知识,你必须知道的Javascript知识点之深入理解作用域链的介绍...
  7. FastDFS配置Nginx模块
  8. Java多线程:线程同步与关键字synchronized
  9. 时间序列信号处理(一)-----变分模态分解(VMD)
  10. 【线性代数】矩阵的算数运算
  11. android studio systrace,Android Systrace 基础知识 -- Systrace 简介
  12. 推荐7款珍藏已久的手机APP,非常实用
  13. 《愤怒的小鸟大电影》分析报告
  14. 强制重启计算机快捷键,电脑强制关机快捷键_电脑强制关机的快捷键
  15. 什么叫原子操作?使用这个东西有什么目的?
  16. 360剑灵洪门崛起服务器维护,剑灵洪门崛起公益服,年度bt无限元宝满v平台,快速升级及上手攻略...
  17. 关于小容量固态硬盘可分区大小远小于实际可用空间的解决方案
  18. Android9.0中应用如何通过SAF框架写入外置SD卡
  19. 项目升级,无缝对接 .NET 5
  20. LeetCode高频200题练习记录

热门文章

  1. 矿大北京迅飞组 | 愿热爱长存!
  2. cesium实现正多边形动态扩散墙效果
  3. ppt计算机说课教案,教师资格证面试高中信息技术说课教案:制作幻灯片
  4. 《大数据架构详解》一书第16次重印
  5. 开发者把写了 12 年的软件,开源了!
  6. C语言中system(pause)
  7. Designer Compiler2016与Prime Time2016安装过程的若干问题
  8. (Ryan的Koa系列博客)2.严谨模式(未全部完成)
  9. linux服务器开发(管道创建) socketpair()
  10. Linux实现VLAN