首页 > 其他分享 >.NET Core多线 (5) 常见性能问题

.NET Core多线 (5) 常见性能问题

时间:2023-08-14 09:14:15浏览次数:42  
标签:Core 暴高 多线 线程 NET 多线程 CPU

合集:.NET Core多线程温故知新

 

去年换工作时系统复习了一下.NET Core多线程相关专题,学习了一线码农老哥的《.NET 5多线程编程实战》课程,我将复习的知识进行了总结形成本专题。

本篇,我们来继续复习一下多线程性能问题的相关知识点,预计阅读时间10分钟。

首先,我们可以明确一下,多线程场景下的常见问题一般为:高CPU占用

一、CPU暴高问题

基本认知

CPU暴高大部分情况下都是线程打暴的!

暴高案例

(1)错误地使用List导致的CPU暴高

常见于偶发性CPU暴高案例中,比如使用了List.Insert(0, item) 时在大数据量下(比如20w+)时间复杂度很大 + 扩容机制,性能很差!一般可能是由模糊查询导致的查了大量DB数据出来组装,因此只会在大数据量时才会偶发。

(2)错误地使用String的拼接导致的CPU暴高

大量错误的大字符串(>85K的都会进LOH)拼接导致LOH频繁触发GC导致CPU暴高。建议使用StringBuilder来重构,但要设置一个合适的初始容量Capacity从而避免频繁对象申请和内存复制。

(3)非线程安全的Dictionary导致的CPU暴高

在多线程环境下使用非线程安全的Dictionary.Contains(key)时导致了在内部实现方法FindEntry(key)时出现了死循环(Entry结构体的next指针指向了自己,由于其他线程也正在Insert、Remove、Update等操作),然后多线程环境下可能有多个死循环一起把CPU打暴了!建议使用线程安全的ConcurrentDictionary结构

(4)lock convoy(锁护送)导致的CPU暴高

在多线程环境下频繁的上下文切换导致,比如每个线程被分配了30ms时间片,但只执行了5ms就被卡主了,即每个请求都有一个lock锁。之前Edison所在的Y公司项目中的JSON-RPC的PreRequest就是这种情况。建议使用批量操作,降低串行化的 lock 个数,不要去玩锁内卷。

(5)应用服务器错误地配置32位导致的CPU暴高

多线程环境下某个方法读取了大量数据(50w+)导致了内存不够用进而引发GC频繁回收进而导致CPU暴高。这常常发生部署在IIS上的.NET Framework Web应用程序:

  • 32bit最高只能吃4G内存;
  • 32bit的临时代(Gen0+Gen1)大概只有不到100M的内存空间;
  • 在IIS服务器模式下,GC会临时征用托管线程充当GC回收线程。

快速解决:将IIS的应用程序域 配置中的 “启用32bit应用程序” 改成False

二、一些实际案例

案例背景

在Edison的前任Y公司,我们做了一些性能优化的措施,提高了系统的稳定性。这里假设之前的系统(大单体)域名为 cj.wzy.cn,每天平均UV(独立用户数) 10000~15000个,平均每天PV(页面浏览数)大概20000~25000个,实时用户数UV(高峰期)800~1000个。虽然这个数值并不高,但是对于这个已经运行了7年多的大单体老系统(.NET 4.5的大Shi山)而言,已经是线上很不稳定了,经常可以看到客服发来的客户抱怨的ticket。

优化内容

(1)优化了一堆年久失修的基础组件

未优化之前存在的问题:

  • jsonrpc的全局PreRequest方法中存在大量 lock convoy (锁护送) 导致线程频繁的上下文切换

    • 比如:每个线程被分配了30ms时间片,但只执行了5ms就被卡主了,即每个请求都有一个lock锁

  • 封装的LocalMemoryCache类基于ReaderWriterLocakSlim对本身就是线程安全的MemoryCache类做线程安全控制

    • 用户态自旋 => 用户态 转 内核态 => 造成CPU压力升高

  • 团队以前自己封装的一个 KafkaHelper 的 Send 方法中加锁范围过大导致等待时间较长

  • ......

(2)优化了一堆慢SQL

未优化之前存在的问题:随着数据量的不断增加,老业务的SQL脚本包含了很多聚合函数、临时表操作 以及 未命中索引的查询条件,解决办法就是SQL优化,对比执行计划 + DBA Review后上线。

(3)优化了IIS的基本配置

未优化之前的问题:部分应用服务器特别是自建的文件服务,经常发生由于配置了“启用32位应用程序”导致的内存不够(因为32位应用最大可用4G内存)用进而引发GC频繁回收进而导致CPU暴高。

解决办法就是将启用32位应用设为False,然后参考一些IIS配置的最佳实践去做了一遍。

当然,根本解法还是去分析自建文件服务中耗内存的地方去优化代码。不过由于当时的物理服务器都是128G的内存且业务场景中也确实存在上传大文件的需求,因此耗内存的地方也暂时搁置去解决了。

(4)优化了滥用Parallel并行库的接口

未优化之前存在的问题:部分耗时较长的Job不加限制的使用 Parallel.ForEach 等方法造成所有CPU Core都被占用并持续数秒,造成CPU>=90%优化后增加了统一的设置的MaxParallelOptions,修复所有滥用的地方传递进去,默认只会用到CPU内核数量的一半。

(5)新增了一台DB服务器分摊压力

有一次因为XXXXXReadDB少了一台,本来是1台写库,2台读库,突然少了一台,导致XXXXXReadDB CPU暴高,应用程序段的DB连接超时严重进而造成延时较多,请求对接,应用程序频繁挂掉。因此后续DBA新增了一台读库,组成1主3从的配置,应用程序段通过切分 合同查询 的业务查询 到 XXXXXReadDB04,所有Job的查询都走XXXXXReadDB03,将流量分摊到不同的读库,保证核心用户的查询流量的可用性。

(6)新增了两台应用服务器分流压力

2021年开始研发中心内部各团队应用开始疯狂调用该系统接口,每分钟请求量达到了1500+左右,造成了原本只是对外部客户服务的应用服务器压力增大,因此新增了两台应用服务器将所有其他团队的内部应用的service请求流量切分到独立的三台服务器上,内外部客户的流量分开,优先保证外部客户的可用性。

未完成的事情

这一切的根因都是因为这七年来这个系统所在的团队单纯拼命的干业务迭代,往原本设计就不佳的大单体系统中堆了太多的屎山,造成了太多的技术债并未及时地去偿还。我们也原本想极力推荐将其拆分后升级到.NET Core或最新的.NET技术,基于.NET Core + 容器化技术 + 开源项目去做较低成本的升级改造,可是计划赶不上变化,当公司从阿什么味的公司找来一高P来做技术总监之后,研发中心所有的Team Leader基本都换成了阿什么味背景的或者靠近阿什么味领导的。此后,所有的计划都是围绕着Java从0到1花费大量成本重构整个大系统来进行,用他们的话来说就是降本增效只能靠Java而不是.NET。公司里整个Java圈子的高级开发者对.NET的认识也还是停留在10年前,我们的发声已变得微不足道,政治正确才是明哲保身的唯一出路。

在这里,Edison还是祝愿Y公司能够越走越好。

参考资料

一线码农,腾讯课堂《.NET 5多线程编程实战

不明作者,《Task调度与await》

 

作者:周旭龙

出处:https://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

标签:Core,暴高,多线,线程,NET,多线程,CPU
From: https://www.cnblogs.com/edisonchou/p/dotnet_multithread_learning_notes_chap5.html

相关文章

  • java 用CompletableFuture来实现多线程查询和结果合并
    多线程查询结果合并使用CompletableFuture来实现多线程查询和结果合并。CompletableFuture提供了一种方便的方式来协调异步任务并处理其结果。下面是一个使用CompletableFuture的示例:importjava.util.ArrayList;importjava.util.List;importjava.util.concurrent.CompletableF......
  • c++多线程
    ......
  • ASP.Net MVC文件访问控制
    程序需求:通用的可以控制某个文件夹下所有所有文件的访问,且可后期扩展文件根目录下增加“FileAccessControl.cs”的一般处理程序,代码如下:(文件名可以自定义)///<summary>///用于文件是否可以访问的判断///</summary>publicclassFileAccessControl:IHttpHandler{pu......
  • Netty源码学习1——NioEventLoopGroup的初始化
    系列文章目录和关于我零丶引入netty源码学习中,大家maybe都接触到如下的helloworld——netty客户端启动的demo:映入眼帘的第一个类就是NioEventLoopGroup,很多文章上来就是是Netty中的核心类,啥Channel,Pipeline,Context,Boostrap一通劈里啪啦,我看起来比较费劲。so本文不会上来就给......
  • CorelCAD中文版下载-CorelCAD 2021(CAD设计工具) 官方版特色
    CorelCAD是一款CAD软件,可以帮助用户设计和绘制2D和3D图形。它提供了许多功能和工具,包括绘图、编辑、注释、测量和布局等。CorelCAD支持多种文件格式,包括DWG、DXF、DWF和PDF等,可以与其他CAD软件进行互操作。此外,CorelCAD还提供了一些高级功能,例如3D建模、渲染、动画和脚本等,可帮助用......
  • 注册中心 —— SpringCloud Netflix Eureka
    Eureka简介Eureka是一个基于REST的服务发现组件,SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务注册与发现,同时提供了负载均衡、故障转移等能力,目前Eureka2.0已经不再维护,故不推荐使用Eureka有两种角色组件:EurekaServer:服务注册中......
  • java.lang.NoSuchMethodError: com.baomidou.mybatisplus.core.toolkit.StringUtils.i
    1、原因这是由于两个版本不一致导致的;<!--mybatis-plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version&......
  • C#多线程环境下调用 HttpWebRequest 并发连接限制
    .net的HttpWebRequest或者 WebClient 在多线程情况下存在并发连接限制,这个限制在桌面操作系统如windowsxp,windows7下默认是2,在服务器操作系统上默认为10.如果不修改这个并发连接限制,那么客户端同时可以建立的http连接数就只有2个或10个。对于一些诸如浏览器或网络......
  • oracle归档日志暴增原因分析,Oracle归档日志满导致数据库性能异常慢 转发 https://b
    ============= oracle数据库archivelog暴增分析====================前言归档量突然增长到981G/天,导致归档目录使用率告警归档日志量异常暴增会导致磁盘空间爆满,数据库异常1、归档日志量统计SELECTTRUNC(FIRST_TIME)"TIME",SUM(BLOCK_SIZE*BLOCKS)/1024/1024/102......
  • springmvc学习之com.fasterxml.jackson.core:jackson-databind:pom:2.15.2 failed to
    -错误的原因是我们通过坐标依赖导入的jar包没有完全下载,也就是下载了一半就停了,是个下载类型的文件而不是真正的jar包,出现这种错误的原因典型的就比如我这种情况,正在下载的时候断网了,然后这个网络链接突然中断,此时文件就是一个损坏的半成品,Maven中的代码似乎不能像迅雷那样继续下......