不可忽视的 .NET 应用5大性能问题(2)

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

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

解决的办法有两种:

仔细检查同步的代码,以确定是否存在其他可行办法

限制同步代码块的范围

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

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

4.潜在的数据库问题

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

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

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

分析 SQL 语句

确定查询的执行计划

利用人工智能生成备选的 SQL 语句

确定所有备选方案的执行计划

提出最佳的查询方式来完成目标

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

5、潜在的基础架构问题

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

不可忽视的 .NET 应用5大性能问题

 图3.NET分层执行模型

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

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

您可能感兴趣的文章:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wjwwjw.html