音效素材网提供各类素材,打造精品素材网站!

站内导航 站长工具 投稿中心 手机访问

音效素材

不可忽视的 .NET 应用5大性能问题
日期:2021-09-07 22:12:55   来源:脚本之家

实现有效 APM 策略所面临的挑战:

  • 代码依赖
  • 过度或不必要的日志
  • 同步与锁
  • 潜在数据库问题
  • 潜在的基础架构问题

1、代码依赖

开发程序是一项具有挑战性的工作。你不仅要为了满足商业需求而建立程序逻辑,还要选择最合适的代码库和工具来帮助你。你能想象自己创建所有的日志管理代码,XML 和 JSON 解析逻辑,或所有的序列化库么?你当然可以编写代码来完成这些事,但是诸多开源开发者团队已经做好了这些事情,你又何必亲力亲为呢?此外,如果你正在与第三方系统集成,你会自己读完专有的通信协议规范,还是购买供应商提供的库帮你完成呢?

我相信你会同意:如果有人已经解决了你的问题,使用他的解决办法会比自己想办法解决效率更高。如果这是一个已经被许多公司采用的开源项目,那么很可能它已经经过完备的测试,文档充足,而且你应该找得到许多使用教程。

然而,使用依赖库是有危险的。你需要回答以下问题:

  • 这个库真的写得很好并且已经充分测试了吗?
  • 你是否用与众多公司一样的方式使用这个库?
  • 你的使用方式是否正确?

请确保在选择外部库之前进行一些调查,如果你对某个库的性能有什么疑问,那就进行一些性能测试。开源项目很好的地方在于你可以访问它们的全部源代码以及测试套件和构建流程。下载它们的源代码,执行编译过程,并查看测试结果。如果你看到很高的测试覆盖率,那么就可以比没有测试案例时信心百倍!

最后,确保正确地使用依赖库。如果正确使用,ORM 工具的确能够大大提高性能。ORM 工具的问题在于,如果你不花时间去学习如何正确地使用它,你就会轻易的砸自己脚,破坏自己的应用性能。关键就在于如果不花时间学习这些工具,本应帮助你的工具反而会伤害你。

2、过度或不必要的日志

日志记录是调试工具库里的强大武器,可以帮助你识别应用执行过程中在特定时间内可能发生的异常。当错误发生时,捕捉错误信息并收集尽可能多的上下文信息是非常重要的。然而,简洁地捕捉错误条件和过度记录之间是有差别的。

最普遍的两个问题就是:

  • 多级别异常日志
  • 错误配置生产日志级别

异常日志能帮助你了解应用程序中发生的问题,因而非常重要。但一个常见的问题是,应用程序所有层级的异常都进行记录。例如,你的某个数据访问对象捕获到一个数据库异常,并将该异常传达到服务层。服务层可能会捕捉该异常,并将其传达到网络层。如果我们在数据层、服务层和网络层上都记录该异常,那么我们对此相同的错误条件就有三条堆栈记录。这会导致写入日志文件的额外负担,还会使日志文件充满冗余信息。但这个问题非常普遍,我敢断言,如果你检查自己的日志文件,你很可能会发现多个这样的例子。

生产应用中常见的另一个大的日志问题与日志级别有关。.NET 日志记录器定义了以下日志记录级别(.NET TraceLevel 与 log4net 中的命名会有所不同,但绝对相似):

  • Off
  • Fatal
  • Error
  • Warning
  • Info
  • Verbose / Debug

在生产应用程序中,你应该只记录 error 或 fetal 级别的日志语句,在更宽松的环境中,捕捉 warning 甚至 info 级别的日志信息也完全可以,但是一旦应用投入生产环境,用户负载将迅速填满日志并使应用程序陷入瘫痪。如果你不经意地将生产环境下的应用日志级别设为 debug,应用的响应时间比正常情况下高两或三倍都不奇怪!

3、同步与锁

有时候,你想确保应用代码中每次只有一个线程执行一段代码子集。 例如,读取单线程规则执行组件之类的共享软件资源,以及文件句柄或网络连接之类的共享基础架构资源。.NET 框架提供了许多不同类型的同步策略,包括锁/监视器、进程间互斥,和读/写锁这类的专用锁。

不管你为什么要同步代码或者选择什么机制实现代码同步,都会导致一个问题:那就是有部分代码一次只能由一个线程执行。 设想去超市,只有一个收银员在工作:许多人进入商店,浏览商品,将商品放进购物车里,但某一时候,他们不得不排队以进行支付。在这个例子中,购物是多线程的,每个人都代表一个线程。然而结账是单线程的,这意味着每个人都要花费排队付款的时间。这个过程如图1所示。

 图1:线程同步

我们有七个线程,都需要访问一段同步代码块,所以它们依次获得权限访问该代码块,执行其功能,然后继续。

在图2中总结了线程同步的过程。 

图2 线程同步过程

首先,为特定的对象(System.Object 派生)创建锁,意味着当一个线程试图进入同步代码块时必须获取该同步对象的锁。如果该锁可用,则该线程被授予执行同步代码的权限。在图2中的例子中,当第二个线程到达时,第一个线程已经占有了该锁,所以第二个线程被强制等待,直到第一个线程执行完毕。当第一个线程执行结束时,会释放该锁,然后第二个线程被授予访问权限。

正如你可能猜测到的,线程同步将给 .NET 应用带来一个极大的挑战。我们设计应用程序时,希望其能支持数十个甚至数百个同步请求,但线程同步会把所有处理这些请求的线程串行化,导致性能瓶颈!

解决的办法有两种:

  • 仔细检查同步的代码,以确定是否存在其他可行办法
  • 限制同步代码块的范围

有时候,你要访问必须同步的共享资源,但很多时候,你可以用完全避免同步的方法重新解决该问题。例如,我们之前使用的规则过程引擎有单线程的要求,因此拖慢了程序中所有请求的执行速度。这显然是一个设计上的缺陷,我们可以用一个可以并行工作的库取代之。你需要问自己是否有更好的选择:如果你在往一个本地文件系统写入信息,你是否可以把信息发送给某项服务,再由该服务将信息存储到数据库中?你是否可以将对象设为不可变,从而无论是否有多线程访问它都没关系?等等,等等…

对于那些必须要同步的代码段,请合理地选择锁。你的目标是将同步代码块隔离以满足最低限度的同步要求。通常最好是定义一个特定的对象进行同步,而不是对包含同步代码的对象进行同步,因为你可能会在不经意间拖慢该对象的其他交互。最后,考虑使用读/写锁,而不是标准的锁,这样,你可以在资源只进行同步变化时,允许读操作。

4.潜在的数据库问题

几乎所有的内容应用最终都会涉及到向/从数据库或文档存储储存/检索数据。因此,数据库、数据库查询,以及存储过程调优对应用程序的性能来说是最重要的。

程序架构师/开发人员和数据库架构师/开发人员之间有一个哲学性的划分。应用程序架构师倾向于认为所有的业务逻辑都应该驻留在应用程序中,数据库应该只提供访问数据的通道。另一方面,数据库架构师更倾向于认为将业务逻辑推到数据库中更有益提高性能。这个划分的答案很可能就是介于两者之间。

作为一个应用程序架构师,我倾向于将更多的业务逻辑应用在程序当中,但我完全承认数据库架构师能更好的理解数据和与数据交互的最佳方式。我认为,这两个群体之间的协同合作才能产生最佳的解决方案。但是,不管你倾向于哪一方,请确保你的数据库架构师检查你的数据模型,所有的查询语句和存储过程,他们都有丰富的知识帮助你以最佳的方式来调整和配置数据库,他们有大量的工具可以为你调整查询语句。例如,有一些工具可用于 SQL 调优,遵循以下这些步骤:

  • 分析 SQL 语句
  • 确定查询的执行计划
  • 利用人工智能生成备选的 SQL 语句
  • 确定所有备选方案的执行计划
  • 提出最佳的查询方式来完成目标

当我在写数据库查询代码时,我使用了这类工具,并在高负载情况下量化了结果,一些细微的调整和优化,都能导致极大的性能提升。

5、潜在的基础架构问题

之前提过,.NET 应用运行在分层的环境中,其层级结构如图3所示:

 图3.NET分层执行模型

你的应用程序运行在 ASP.NET 或是 Windows Forms 容器中,使用 ADO 库与运行在 CLR 内部的数据库交互,而 CLR 运行在操作系统中,操作系统又运行在硬件里。而该硬件又与其他包含不同技术堆栈的硬件通过网络相连。在你的应用与外部环境之间,以及在应用的组件之间,通常有多个负载平衡器。我们还有 API 管理服务以及多级缓存。所有这一切,都是为了说明,基础构造数量庞杂,都可能影响应用程序的性能!

因此,你必须细致地调整基础架构。检查你的应用组件和数据库所运行的操作系统和硬件设备,以确保它们的最佳表现。测量服务器之间的网络延迟,并确保你有足够的带宽来满足应用程序之间的交互。检查缓存,确保较高的缓存命中率。分析负载平衡器的行为以确保请求很快地分发到所有可用的服务器。总之,你需要全面检查应用程序的性能,既包括应用业务交易也包括支持它们的基础架构。

    您感兴趣的教程

    在docker中安装mysql详解

    本篇文章主要介绍了在docker中安装mysql详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编...

    详解 安装 docker mysql

    win10中文输入法仅在桌面显示怎么办?

    win10中文输入法仅在桌面显示怎么办?

    win10系统使用搜狗,QQ输入法只有在显示桌面的时候才出来,在使用其他程序输入框里面却只能输入字母数字,win10中...

    win10 中文输入法

    一分钟掌握linux系统目录结构

    这篇文章主要介绍了linux系统目录结构,通过结构图和多张表格了解linux系统目录结构,感兴趣的小伙伴们可以参考一...

    结构 目录 系统 linux

    PHP程序员玩转Linux系列 Linux和Windows安装

    这篇文章主要为大家详细介绍了PHP程序员玩转Linux系列文章,Linux和Windows安装nginx教程,具有一定的参考价值,感兴趣...

    玩转 程序员 安装 系列 PHP

    win10怎么安装杜比音效Doby V4.1 win10安装杜

    第四代杜比®家庭影院®技术包含了一整套协同工作的技术,让PC 发出清晰的环绕声同时第四代杜比家庭影院技术...

    win10杜比音效

    纯CSS实现iOS风格打开关闭选择框功能

    这篇文章主要介绍了纯CSS实现iOS风格打开关闭选择框,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作...

    css ios c

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的办法

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的

    Win7给电脑C盘扩容的办法大家知道吗?当系统分区C盘空间不足时,就需要给它扩容了,如果不管,C盘没有足够的空间...

    Win7 C盘 扩容

    百度推广竞品词的投放策略

    SEM是基于关键词搜索的营销活动。作为推广人员,我们所做的工作,就是打理成千上万的关键词,关注它们的质量度...

    百度推广 竞品词

    Visual Studio Code(vscode) git的使用教程

    这篇文章主要介绍了详解Visual Studio Code(vscode) git的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...

    教程 Studio Visual Code git

    七牛云储存创始人分享七牛的创立故事与

    这篇文章主要介绍了七牛云储存创始人分享七牛的创立故事与对Go语言的应用,七牛选用Go语言这门新兴的编程语言进行...

    七牛 Go语言

    Win10预览版Mobile 10547即将发布 9月19日上午

    微软副总裁Gabriel Aul的Twitter透露了 Win10 Mobile预览版10536即将发布,他表示该版本已进入内部慢速版阶段,发布时间目...

    Win10 预览版

    HTML标签meta总结,HTML5 head meta 属性整理

    移动前端开发中添加一些webkit专属的HTML5头部标签,帮助浏览器更好解析HTML代码,更好地将移动web前端页面表现出来...

    移动端html5模拟长按事件的实现方法

    这篇文章主要介绍了移动端html5模拟长按事件的实现方法的相关资料,小编觉得挺不错的,现在分享给大家,也给大家...

    移动端 html5 长按

    HTML常用meta大全(推荐)

    这篇文章主要介绍了HTML常用meta大全(推荐),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参...

    cdr怎么把图片转换成位图? cdr图片转换为位图的教程

    cdr怎么把图片转换成位图? cdr图片转换为

    cdr怎么把图片转换成位图?cdr中插入的图片想要转换成位图,该怎么转换呢?下面我们就来看看cdr图片转换为位图的...

    cdr 图片 位图

    win10系统怎么录屏?win10系统自带录屏详细教程

    win10系统怎么录屏?win10系统自带录屏详细

    当我们是使用win10系统的时候,想要录制电脑上的画面,这时候有人会想到下个第三方软件,其实可以用电脑上的自带...

    win10 系统自带录屏 详细教程

    + 更多教程 +
    ASP编程JSP编程PHP编程.NET编程python编程