开发高性能ASP.NET应用

本文是“.NET Conf China 2022”上我的一个分享,这里更细化的分享出来。

分享分为四个部分:

  1. 制定指示

  2. 设计应用

  3. 正确测试

  4. 性能优化

高性能:不一定是架构出来的,但一定是优化出来的。

  • 制定指标-收集

    首先把项目中的热路径API和核心API找出来,然后分析每个API是CPU密集型的,还是内存密集型的,以供在后面测试参考或对API的判断。

  • 制定指标-制定

    TPS=并发线程*1000/ART,这是TPS和平均响应时间的公式。这里的表格相对完整,作为开发的性能测试,有时也可以只要求响应时间和TPS。或要求TPS和P95,P99。有时成功率很敏感,不管发性能怎么样,成功率必须100%,这是根据业务的类型要求的,特别是和钱有关的请求,要求都比较高。

    某API指标

    指标名称

    指标值

    业务指标

    TPS(2C2G)

    2000

    响应时间

    ART

    10

    P95

    12

    P99

    15

    成功率

    100%

    并发线程

    20

    稳定性指标

    压力持续时间

    >=8h

    压力阈值

    CPU <80%,TPS≈2000

    内存泄露

    TPS波动

    <5%

    应用资源(2C2G)

     MEM

    <2G

    CPU最大使用率

    <90%

    DB资源(8C8G)

     MEM

    <8G

    CPU最大使用率

    <90%

    缓存(1C1G)

    MEM

    <80%

    CPU最大使用率

    <90%

  • 设计应用-通用设计

    开发人员要了解通用状态下的设备情况,比如CPU的缓存,内存,硬盘之间的关系,比如速度是在依次减少,成本在降低。还要了解各种网络协速度,I/O的速度,以及使用各种数据库的速度通常的阈值是什么样的。

762e1f158e6b6697641758c0f5ac08e4.png

提升性能的两个法宝:用缓存和用Queue,缓存可以让使用数据速度更快,Queue可以分隔复杂业务,让吞吐量更高,合理有效的使用两种技术可以很大的提升性能。

  • 设计应用-.NET体系

  • 使用异步:Demo

//同步方法
app.MapGet("/sync", () =>
{using (var con = new MySqlConnection(connectionString)){var result = con.Query<int>("select sleep(6)");Console.WriteLine($"sync:{DateTime.Now}");return result;}
});
//异步方法,没有CancellationToken 
app.MapGet("/async", async () =>
{using (var con = new MySqlConnection(connectionString)){var result = await con.QueryAsync<int>("select sleep(6)");Console.WriteLine($"sync:{DateTime.Now}");return result;}
});
//异步,有CancellationToken 
app.MapGet("/asyncwithtoken", async (CancellationToken token) =>
{using (var con = new MySqlConnection(connectionString)){var result = await con.QueryAsync<int>(new CommandDefinition("select sleep(6)", cancellationToken: token));Console.WriteLine($"sync:{DateTime.Now}");return result;}
});

通过postman请求三个api,然后取消,会发现前两个api始终会执行完成,并输出时间;第三个会在取消后停止响应。

58fcce56ae5e58649eea1b97c6aec1e7.png

正确使用异步,可以有效地提升服务端的资源使用状况。

  • 谨防阻塞:

记一次性能故障排查

桂素伟,公众号:桂迹记一次性能故障排查

  • 大集合化整为零:用最正确的集合来处理数据,不要在集中存放大量数据,这样不管对内存或之后的运算,造成负担。同时要从业务层次评估计集合的最大上限。 

  • 避免在Host生成文件

再记一次Memory Leak分析

桂素伟,公众号:桂迹再记一次Memory Leak分析

  • 复杂方法要比对:

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
using PerformanceDemo;
using System.Collections.Generic;
using System.Xml.Linq;var summary = BenchmarkRunner.Run(typeof(CustomTypeTest));public class CustomTypeTest
{ [Benchmark][Arguments(2000)]public Dictionary<string, SBook> GetBook1(int count){var sbookDic = new Dictionary<string, SBook>();for (var i = 0; i <= count; i++){sbookDic.Add($"张{i}丰", new SBook(){Id = i,Name = "C#从入门到精通",Author = $"张{i}丰",Title = "C#1.0",Description = "这是一本书"});}return sbookDic;}[Benchmark][Arguments(2000)]public Dictionary<string, Book> GetBook2(int count){var bookDic = new Dictionary<string, Book>();for (var i = 0; i <= count; i++){bookDic.Add($"张{i}丰", new Book(){Id = i,Name = "C#从入门到精通",Author = $"张{i}丰",Title = "C#1.0",Description = "这是一本书"});}return bookDic;}[Benchmark][Arguments(2000)]public List<Book> GetBook3(int count){var bookList = new List<Book>();for (var i = 0; i <= count; i++){bookList.Add(new Book{Id = i,Name = "C#从入门到精通",Author = $"张{i}丰",Title = "C#1.0",Description = "这是一本书"});}return bookList;}[Benchmark][Arguments(2000)]public List<SBook> GetBook4(int count){var sbookList = new List<SBook>();for (var i = 0; i <= count; i++){sbookList.Add(new SBook{Id = i,Name = "C#从入门到精通",Author = $"张{i}丰",Title = "C#1.0",Description = "这是一本书"});}return sbookList;}
}
public class Book
{public int Id { get; set; }public string Name { get; set; }public string Description { get; set; }public string Title { get; set; }public string Author { get; set; }
}
public struct SBook
{public int Id { get; set; }public string Name { get; set; }public string Description { get; set; }public string Title { get; set; }public string Author { get; set; }
}

下面是比较结果:

28ec49fdbbb03dab584922b701c4a249.png

  • 让每个API轻巧快速

  • 有一颗追求性能的心——关注.NET版本

    关于在开发层次的性能注意事项有很多,这是根据不同的项目,使用不同的类库决定的,上面只是我性能化化中的几个代表性场景。

  • 设计应用-发布

配置:GC方式 工作站方式,服务器方式:CPU使用率比内存更重要,服务器GC性能更好;内存利用率较高而 CPU 使用率相对较低,工作站 GC 性能更高。

发布方式:默认和R2R首次请求时间和体积不同


普通模式

R2R模式

AOT模式

大小

29.8 MB

62.2 MB

19.5M

首次请求用时

360ms

90ms

20ms

  • 正确测试

  • 测性能的正确姿势

尽量与生产环境一致

要有监控,通过监控数据对比发现问题

不要打满资源:CPU<90%,内存少于最大值

让子弹多飞会儿,观察内存是有什么不一样

  • 遇到问题借助工具

dotnet-dump

dotnet-counters

  • 前人经验也很宝贵

https://learn.microsoft.com/zh-cn/dotnet/core/diagnostics/

  • 性能优化

  • 减少响应时间:

优化&简化流程

优化调用链路上的函数

把关系数据库操作转成缓存操作

用BenchmarkDotNet

  • 提升TPS:

优先降低性能测中的较高资源

让应用性能是线性的,可以轻松地通过扩容来提升TPS

经过上面的分享,可以得出:

高性能:一定是架构出来的,但一定是优化出来的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/280608.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django08-1:模型层(ORM)--聚合查询/分组查询/F与Q查询/开启事务/常用字段及参数/自定义字段/数据库查询优化

聚合查询 单独使用时&#xff0c;用aggregate 1.只要是跟数据库相关的模块 基本都在django.db.models里面 如果没有应该在django.db里面 2. 聚合查询通常配合分组使用 from django.db.models import Avg, Sum, Max, Min, Count# 1.所有书的平均价格 resmodels.Book.objects.…

记事本状态栏不会自动_如何在记事本中同时启用状态栏和自动换行

记事本状态栏不会自动The status bar in Windows’ Notepad displays the current line number and column number of the cursor location. However, if you find that the Status Bar option on the View menu is grayed out, it may be because you have Word Wrap enabled…

极端高温导致澳大利亚断网

&#xfeff;西澳大利亚首府珀斯因恶劣天气出现了网络连接问题&#xff0c; 网络故障不是由于暴风雨或闪电引起的&#xff0c;而是极端高温。本周一是珀斯有记录以来第六热的天&#xff0c;当天最高温度达到了44.4℃。因为创纪录的高温&#xff0c;澳大利亚宽带 服务商iiNet在当…

推荐一款采用 .NET 编写的 反编译到源码工具 Reko

今天给大家介绍的是一款名叫Reko的开源反编译工具&#xff0c;该工具采用C#开发&#xff0c;广大研究人员可利用Reko来对机器码进行反编译处理。我们知道.NET 7 有了NativeAOT 的支持&#xff0c;采用NativeAOT 编译的.NET程序 无法通过ILSpy 之类的传统工具得到源码&#xff0…

并行传输数据和串行传输数据_为什么串行数据传输比并行数据传输快?

并行传输数据和串行传输数据SATA hard drive connections are faster than older PATA hard drive connections and the same can be said for external cabling standards, but this is counter-intuitive: why wouldn’t the parallel transmission be faster? SATA硬盘驱动…

微软让卡塔尔世界杯踏入元宇宙

遵守前一篇公众号文章里的承诺&#xff0c;昨天盆盆在视频号里录制了一段5分钟左右的短视频&#xff0c;讲了江森自控和微软Azure&#xff0c;如何帮助卡塔尔世界杯打造基于元宇宙的数字体育馆。Part.1欢迎扫码关注我的视频号(每天更新元宇宙、云计算和数字化的短视频)。Part.2…

插槽1单通道插槽2双通道_相机双存储卡插槽有什么大不了的?

插槽1单通道插槽2双通道If you paid any attention to the launch of Canon and Nikon’s first full frame mirrorless cameras—the EOS R, Z6, and Z7— you’d have noticed that some people were pretty unhappy that they only came with a single card slot—an SD slo…

python 垃圾回收详解

原文&#xff1a;https://zhuanlan.zhihu.com/p/31150408 总纲策略和垃圾回收系统工作内容引用计数详解标记-清除分代收集循环引用编程应用-常见方法ex 过程详解使用建议触发机制参考文献Python垃圾回收机制--完美讲解&#xff08;Python vs Ruby&#xff09;Python垃圾回收机制…

mac 不能连接wi-fi_如何阻止Mac自动连接到Wi-Fi网络

mac 不能连接wi-fiYour Mac automatically reconnects to Wi-Fi networks you’ve previously connected to. Starting with macOS High Sierra, you can now tell your Mac not to automatically connect to certain Wi-FI networks. Your Mac will remember the Wi-Fi networ…

罗汉塔最少步骤_如何以最少的步骤压缩和密码保护文件?

罗汉塔最少步骤If you have a large batch of files to compress and you want to add password protection to each of them, what is the simplest or quickest way to do so? Today’s SuperUser Q&A post has the answer to a curious reader’s question. 如果要压缩…

IoTSharp中使用X509加密MQTT通讯并实现设备鉴权

IoTSharp支持MQTT协议通过 TLS 1.2 加密通讯&#xff0c; 并可以通过X509证书进行设备认证登录。基本配置在 appsettings.Production.json中需要 指定域名&#xff0c; 并设置EnableTls为true"MqttBroker":{"DomainName":"http://demo.iotsharp.net:2…

django12:form 组件/渲染标签/数据校验/钩子函数/

基本用法 from django import forms# 自己写一个类 class RegForm(forms.Form):username forms.CharField(min_length3,max_length8, label"用户名")password forms.CharField(min_length3,max_length8,label"密码")emailforms.EmailField() 1.校验数据为…

如何快速拥有一个 Web IDE

本文将介绍如何使用 2-3 句指令在几分钟内创建一个 Web IDE 环境。服务器准备如何准备服务器可以参考上文 一键体验 Istio&#xff0c;这里只需要一台即可&#xff0c;示例中的服务器 IP 为&#xff1a;43.154.189.116安装 Web IDE下载安装工具在服务器上&#xff0c;执行以下指…

有了防火墙、IPS、WAF 还需要数据库审计?

本文讲的是 有了防火墙、IPS、WAF 还需要数据库审计&#xff1f;&#xff0c;“我们的网络安全系统中已经有了Web应用防火墙、网络防火墙和IPS&#xff0c;难道还需要数据库审计吗&#xff1f;”很多人有这样的疑问&#xff0c;网络中有层层防护&#xff0c;还不能保护数据库的…

20155339 Exp4 恶意代码分析

20155339 Exp4 恶意代码分析 实验后回答问题 &#xff08;1&#xff09;如果在工作中怀疑一台主机上有恶意代码&#xff0c;但只是猜想&#xff0c;所有想监控下系统一天天的到底在干些什么。请设计下你想监控的操作有哪些&#xff0c;用什么方法来监控。 监控网络连接。当某个…

Linux就该这么学---第七章(LVM逻辑卷管理器)

第七章节-LVM技术逻辑卷管理器(LVM,Logical Volume Manager)1.物理卷(PV,physical Volumn)2.卷组(VG,Volume Group)3.逻辑卷(LV,Logical Volume)基本单元[PE,Physical Extent] 物理卷处于LVM中的最底层&#xff0c;可以将其理解为物理硬盘、硬盘分区或者RAID磁盘阵列卷组建立在…

从Windows XP升级? 这是您需要了解的Windows 7

With Windows XP reaching the end of its long support life, many businesses and individuals are avoiding Windows 8 and upgrading to Windows 7 instead. If you’re a latecomer to Windows 7, here are the basics you need to know. 随着Windows XP使用寿命的延长&am…

Java迭代器原理

1迭代器模式 迭代器是一种设计模式&#xff0c;这种模式用于顺序访问集合对象的元素&#xff0c;不需要知道集合对象的底层表示。 一般实现方式如下&#xff1a;&#xff08;来自&#xff09; public interface Iterator {public boolean hasNext();public Object next(); } pu…

企业版Java EE正式易主 甲骨文再次放手

有人说甲骨文收购的东西大多没有了好下场&#xff0c;这么说虽然有些片面&#xff0c;但是最近一个月Java EE和Solaris的境遇难免让人产生类似的联想。 继笔者上次报道《甲骨文将放弃Java EE 开源基金会双手欢迎》之后&#xff0c;最新消息显示&#xff0c;原本在甲骨文手中的J…

js中各种位置

js中各种位置 js中有各种与位置相关的属性,每次看到的时候都各种懵逼。索性一次总结一下。 clientHeight 内容可视区域的高度。包括padding不包括border、水平滚动条、margin。对于inline的元素这个属性一直是0&#xff0c;单位px&#xff0c;只读元素。offsetHeight offsetHei…