架构设计之分析系统性能问题

news2024/11/25 20:51:01

我们在讨论高性能架构之前,需要先聊聊什么叫高性能,以及如何量化地测试系统的性能。在02 讲中,我们讨论了一些和并发相关的指标。事实上,并发数正是系统性能的核心指标之一,因为高并发会引起系统资源短缺,来不及处理用户请求,就会导致系统性能下降。除了系统并发数,一般说来,和系统性能相关的量化指标还有响应时间和吞吐量。在前面的案例分析中,我们也多次估算过响应时间和吞吐量。我们再重新回顾下这几个指标的定义。

 吞吐量、响应时间和并发数三者之间是有关联性的。

吞吐量=并发数÷响应时间

并发数不变,响应时间足够快,那么单位时间的吞吐量就会相应地提高。以上这些性能指标,我们可以在系统运行期通过监控系统获取,也可以在系统上线前通过性能测试来获取,以此来了解我们系统的性能特性,以及判断系统能否承受预期的高并发压力。

性能测试

性能测试就是使用性能测试工具,通过多线程模拟用户请求,对系统施加高并发的访问压力,得到以上这些性能指标。事实上,随着请求线程数,即并发数逐渐增加,系统的吞吐量和响应时间会呈现出不同的性能特性。具体说来,整个测试过程又可细分为性能测试、负载测试、压力测试三个阶段。性能测试是以系统设计初期规划的性能指标为预期目标,对系统不断施加压力,验证系统在资源可接受的范围内是否达到了性能预期目标。这个过程中,随着并发数的增加,吞吐量也在增加,但是响应时间变化不大。系统正常情况下的并发访问压力应该都在这个范围内。

负载测试则是对系统不断施加并发请求,增加系统的压力,直到系统的某项或多项指标达到安全临界值。这个过程中,随着并发数的增加,吞吐量只有小幅的增加,达到最大值后,吞吐量还会下降,而响应时间则会不断增加。

压力测试是指在超过安全负载的情况下,增加并发请求数,对系统继续施加压力,直到系统崩溃或不再处理任何请求,此时的并发数就是系统的最大压力承受能力。这个过程中,吞吐量迅速下降,响应时间迅速增加。到了系统崩溃点,吞吐量为 0,响应时间无穷大。性能压测工具不断增加并发请求线程数,持续对系统进行性能测试、负载测试、压力测试,得到对应的 TPS 和响应时间,将这些指标画在一个坐标系里,就得到系统的性能特性曲线。

上图中,横轴是系统并发数,左侧黄色纵轴为吞吐量 TPS,对应图中黄色曲线。可以看到,随着并发数增加,系统负载压力也不断增加,系统吞吐量是先上升后下降;右侧蓝色纵轴为响应时间,对应图中蓝色曲线,随着并发负载压力的不断增加,系统响应时间先是缓慢增长,到了某个点后,响应时间急剧增加。通过性能测试,如果发现系统的性能特性并不能满足我们的预期,就需要对系统进行性能优化。

架构方面核心的优化思路有三个:通过分布式集群扩展系统的服务器,降低单一服务器的负载压力;通过缓存的方式降低系统的读负载压力;通过消息队列降低系统的写负载压力。对应的技术方案分别是:负载均衡分布式缓存消息队列,我称之为高性能架构的三板斧。 

负载均衡

所谓负载均衡,就是将高并发的用户请求分发到多台应用服务器组成的一个服务器集群上,利用更多的服务器资源处理高并发下的计算压力,提升整体的性能指标。下图是比较常用的应用层负载均衡。

用户的 HTTP 请求先到达应用层负载均衡服务器,负载均衡服务器从应用服务器集群中选择一台服务器的 IP 地址 (10.0.0.3),然后将 HTTP 请求转发给该服务器。该服务器处理完成后,将响应内容返回给负载均衡服务器,再由负载均衡服务器返回给用户。不同用户并发提交访问请求的时候,负载均衡服务器就会将这些请求分发到不同的应用服务器上,每台应用服务器处理的用户请求并发量都不是很高,而这样构成的一个应用服务器集群却可以承受较高的并发访问压力。

但是,这种应用层负载均衡有个比较大的问题,就是所有请求、响应 HTTP 通信都需要通过负载均衡服务器,而 HTTP 协议又是一个比较重的应用层协议,协议的处理需要消耗比较多的计算资源。也就是说,应用层负载均衡服务器将会是整个应用服务器集群的瓶颈。

因此,应用层负载均衡(Nginx)通常用在规模比较小的集群上,而对于大规模的应用服务器集群,我们使用 IP 层负载均衡或者链路层负载均衡(例如F5)。

IP 层是网络通讯协议的网络层,所以有时候 IP 层负载均衡也叫网络层负载均衡。它的主要工作原理是用户的请求到达负载均衡服务器后,负载均衡服务器会对网络层数据包的 IP 地址进行转换,将其修改为应用服务器的 IP 地址,然后把数据包重新发送出去,请求数据就会到达应用服务器。如下图。 

IP 负载均衡不需要在 HTTP 协议层工作,可以在操作系统内核直接修改 IP 数据包的地址,所以效率比应用层负载均衡高得多。但不管是请求还是响应的数据包,都要通过负载均衡服务器进行 IP 地址转换,而响应的数据通常都会比较大,甚至会超过 IP 负载均衡服务器网卡带宽。因此对于大规模的应用服务器集群,IP 层负载均衡服务器还是会成为响应的流量瓶颈。

优化的方案就是采用链路层负载均衡。链路层负载均衡服务器并不修改请求数据包的 IP 地址,而是修改数据链路层里的网卡 mac 地址,在数据链路层实现负载均衡。应用服务器返回响应数据的时候,因为 IP 地址没有修改过,所以这个响应会直接到达用户的设备,而不会再经过负载均衡服务器。如下图。

链路层负载均衡避免响应数据再经过负载均衡服务器,因而可以承受较大的数据传输压力,目前大型互联网应用大多使用链路层负载均衡。

分布式缓存

负载均衡可以降低单服务器的并发负载压力,但是需要更多的服务器,同时也无法降低数据库的负载压力。为了弥补这些缺陷,我们还需要使用缓存优化系统性能。所谓缓存,就是将要多次读取的数据暂存起来,这样应用程序就不必从数据源重复加载数据了,以此降低数据源的计算负载压力,提高数据响应速度。高并发架构中常见的分布式缓存有三种:CDN、反向代理和分布式对象缓存。

CDN(Content Delivery Network)

即内容分发网络。我们上网的时候,App 或者浏览器想要连接到互联网应用的服务器,需要移动、电信这样的网络服务商为我们提供网络服务,建立网络连接才可以上网。而这些服务商需要在全国范围内部署骨干网络、交换机机房,才能完成网络连接服务。因为这些交换机机房可能会离用户非常近,所以我们自然想到了,互联网应用能不能在这些交换机机房中部署缓存服务器呢?这样的话,用户就可以近距离获得自己需要的数据,既提高了响应速度,又节约了网络带宽和服务器资源。答案是当然可以。这个部署在网络服务商机房中的缓存就是 CDN,因为距离用户非常近,又被称作网络连接的第一跳。目前很多互联网应用大约 80% 以上的网络流量都是通过 CDN 返回的。 

我们有时候需要通过代理上网,这个代理是代理我们的客户端上网设备。而反向代理则是代理服务器,所有的网络请求都需要通过反向代理才能到达应用程序服务器。那么在这里加一个缓存,尽快将数据返回给用户,而不是发送给应用服务器,这就是反向代理缓存。 

 用户请求到达反向代理缓存服务器,反向代理检查本地是否有需要的数据,如果有就直接返回;如果没有,就请求应用服务器,得到需要的数据后缓存在本地,然后返回给用户。同时,只要将后面的应用服务器部署为一个集群,反向代理服务器在请求后面的应用服务器的时候,进行负载均衡选择,那么这个反向代理缓存服务器也就同时成为了前面讨论的应用层负载均衡服务器。也就是说,一台服务器,既做反向代理服务器,也做负载均衡服务器。CDN 反向代理缓存对应用程序是透明的,通常被当做系统前端的一部分。而应用程序如果要使用缓存,就需要分布式对象缓存。分布式对象缓存访问架构如下图。

多台缓存服务器构成一个缓存集群,缓存数据存储在每台服务器的内存中。每个程序需要依赖一个缓存客户端 SDK,通过 SDK 的 API 来访问缓存服务器。应用程序先调用 API,由 API 调用 SDK 的路由算法,路由算法根据缓存的 key 值,计算这个 key 应该访问哪台缓存服务器。路由算法计算得到目标服务器的 IP 地址和端口号后,API 再调用 SDK 的通信模块,将 值以及缓存操作命令发送给具体的某台缓存服务器,最终由这台服务器完成缓存操作。

使用缓存架构可以减少不必要的计算,快速响应用户请求。但是缓存只能改善系统的读操作性能,对于写操作,缓存是无能为力的。我们不能把用户提交的数据直接写入缓存中,因为缓存通常被认为是一种不可靠的存储。

消息队列

优化写操作性能的主要手段是使用消息队列,将写操作异步化。典型的应用程序写数据的方式如下图。 

应用服务器收到用户写操作请求后,调用数据库操作接口,完成数据写入数据库的操作。但是数据库处理速度比较慢,同时又对并发压力比较敏感。大量操作请求同时提交到数据库,可能会导致数据库负载压力太大而崩溃。使用消息队列将写操作异步化如下图。

应用服务器收到用户写操作请求后,不是直接调用数据库,而是将写操作请求发送给消息队列服务器,再由消息消费者服务器从消息队列服务器消费消息,完成对数据库的写操作。

这样会带来两个好处。一方面,用户请求发送给消息队列就可以直接返回响应给用户了,而消息队列服务器的处理速度要远远快于数据库,用户端的响应时间可以极大缩短;另一方面,消息队列写数据库的时候,可以根据数据库的负载能力控制写入的速度,即使用户请求并发很高,也不会导致数据库崩溃,消息队列可以使系统运行在一个性能最优的负载压力范围内。

这种在用户请求高并发的时候控制处理速度,在用户请求低谷的时候,继续处理请求的方式叫做“削峰填谷”,如下图。 

消息队列将直接调用的高峰访问压力推迟到访问低谷的时候处理,使系统保持在性能最优的状态下运行。

小结

这节课的三种高性能架构是最常用的架构性能优化手段,可以解决大多数系统架构性能问题。但是性能优化是一个系统的工程,不问青红皂白,不管三七二十一,上来就是三板斧,那做架构师也未免太容易了些。

性能优化必须有的放矢,必须要了解系统的关键技术设计,以及当前的系统性能指标,然后才能寻找到最合适的性能优化方式。

所以性能优化需要从性能测试开始,具体过程可以总结为以下几步:

  • 进行性能测试,了解系统当前性能指标,发现哪些指标不符合性能需求。
  • 分析系统架构设计与关键技术实现,发现导致性能瓶颈的地方。
  • 进行架构以及代码优化,消除性能瓶颈。
  • 进行性能测试,分析优化是否达到目标。而且性能优化也并不是只能优化架构和代码。

对于一个全球用户访问的系统,在全球各地部署多个数据中心,就近为用户服务可以极大降低网络传输的延迟,提升性能;对于一些少量而重要的数据计算,使用更好的 CPU、更大的内存、更快的硬盘,也就是说,进行垂直伸缩,也可以极大改善性能;而对操作系统、虚拟机进行参数优化,对使用的第三方软件包进行升级改造,有时候也会对性能实现成倍的提升。 

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

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

相关文章

【夜深人静学数据结构与算法 | 第二篇】后缀(逆波兰)表达式

目录 前言: 中缀表达式: 后缀表达式: 中缀表达式转后缀表达式: 后缀表达式计算结果: 总结: 前言: 计算机在计算四则运算的时候,由于括号以及运算优先级的存在,并不…

大数据Doris(四十一):Routine Load严格模式和导入案例

文章目录 Routine Load严格模式和导入案例 一、严格模式 二、严格模式导入Kafka数据到Doris Routine Load严格模式和导入案例

【Thunder送书 | 第三期 】「Python系列丛书」

文章目录 前言《Python高效编程——基于Rust语言》《Python从入门到精通》《Python Web深度学习》《Python分布式机器学习》文末福利 | 赠书活动 前言 Thunder送书第三期开始啦!前面两期都是以【文末送书】的形式开展,本期将赠送Python系列丛书&#xff…

下载安装Visual Studio 2017 Community 来编译NIM_PC_DEMO

1、下载vs2017的引导程序 官方并没有为vs2017提供离线安装包,所以我们选择在线安装。 首先我们下载vs2017的引导程序:Visual Studio 2017安装包 包含如下4个文件: vs_Community.exe: 社区版,免费。但是需要登录微软…

第四节 字符串

文章目录 字符串1.1 字符串介绍1.2 字符串的定义1.3 字符串的输入和输出1.3.1 字符串的索引 1.4 字符串切片1.4.1 切片几种写法 1.5 字符串常用函数1.5.1 find()1.5.2 index()1.5.3 扩展知识: rfind()和rindex()1.5.4 count()1.5.5 replace()1.5.6 split()1.5.7 join() 1.6 字符…

C++常用STL容器--list

C常用STL容器--list list基本概念list构造函数list赋值、交换list大小操作list插入、删除list数据获取list反转、排序 list基本概念 功能: 将数据进行链式存储 链表(list) 是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针…

高并发架构设计方法

我们知道,“高并发”是现在系统架构设计的核心关键词。一个架构师如果设计、开发的系统不支持高并发,那简直不好意思跟同行讨论。但事实上,在架构设计领域,高并发的历史非常短暂,这一架构特性是随着互联网,…

Linux之配置网络

目录 Linux之配置网络 网络接口 网络类型符号 类型 设备类型或位置选择 类型 网络连接 网络配置 三种方法 方法1 --- 使用nmtui进行网路配置 方法2 --- 使用nmcli设置 方法3 --- 修改配置文件 方法4 --- cockpit配置示意图 使用ip命令配置临时生效的网络连接 测试网…

chatgpt赋能python:Python收集数据的介绍

Python收集数据的介绍 Python是一个多功能的编程语言,其拥有强大的数据收集和分析功能。为了充分利用Python的数据处理和挖掘功能,一些优秀的数据收集工具被开发出来。在本文中,我们将介绍如何使用Python收集数据,并介绍一些常用…

总结900

目标规划: 月目标:6月(线性代数强化9讲,考研核心词过三遍) 周目标:线性代数强化3讲,英语背3篇文章并回诵,检测 每日规划 今日已做 1.读六级阅读 2.完成学习通考试(没做计划) 3.阅…

[编程工具]Unity配表导出工具TableExporter1.1

[ 目录 ] 0. 前言1. 属性拓展优化(1)反射获取转化函数 TryParse(2)反射获取EmptyReplace(3)属性类型(4)属性拓展 2. 模板处理(1)替换内容(2&#…

chatgpt赋能python:Python如何放大界面——实用技巧

Python如何放大界面——实用技巧 在Python中,很多时候我们需要放大界面来更清楚的展示内容。这篇文章将介绍Python放大界面的方法。 放大界面的原理 在Python中,放大界面的原理实际上就是改变窗口的大小。我们可以通过改变窗口的尺寸实现放大效果。 …

LuatOS-Air AT应用指南--RNDIS

简介 RNDIS是指Remote NDIS,基于USB实现RNDIS实际上就是TCP/IP over USB,就是在USB设备上跑TCP/IP,让USB设备看上去像一块网卡。从而使Windows /Linux可以通过 USB 设备连接网络。 Window系统 window系统支持RNDIS直接用usb连接就可以使用&a…

2023/6/14总结

JS的学习: JavaScript是一种运行在客户端(浏览器)的编程语言,实现人机交互的效果 主要作用: 网页特效表单验证数据交互 JS的组成 ECMAScript 规定了js基础的语法核心知识 Web APIs DOM:操作文档,对页面…

简单的TCP网络程序·线程池(后端服务器)

目录 版本四:线程池 注意事项 文件:Task.hpp -- 任务单独为一个文件 组件:日志修改 新函数:vprintf() 可变参数的提取逻辑 vfprintf()的工作原理 初始化一个va_list 日志准备 获取时间小知识 日志初版 日志启动测试 …

DAY23:二叉树(十三)二叉树的最近公共祖先+二叉搜索树的最近公共祖先

文章目录 236.二叉树的最近公共祖先思路完整版后序遍历的进一步理解为什么左为空右不为空的时候return right这个逻辑是否包含p/q本身就是公共祖先的情况 235.二叉搜索树的最近公共祖先思路关于遍历顺序 递归法最开始的写法debug测试修改版 迭代法最开始的写法为什么最开始这种…

chatgpt赋能python:Python收费介绍

Python收费介绍 什么是Python? Python是一种高级的、解释性、面向对象、纯粹的动态语言,多用于快速应用程序开发、脚本编写、系统管理任务等。它有一个简单直观优美的语法,非常容易学习。 Python的收费形式 Python语言本身是免费的,任何…

chatgpt赋能python:Python如何操作Word文档

Python如何操作Word文档 简介 Python是一种高级编程语言,具有易于学习和使用、高效、可移植性强等优点。相信许多Python开发者都遇到过需要使用Python操作Word文档的情况。本文旨在介绍如何使用Python操作Word文档,使开发者能够方便地实现自己的需求。…

chatgpt赋能python:Python怎么改为中文?

Python怎么改为中文? Python是一种高级编程语言,具有易读性、简单性和可扩展性的特点。它广泛应用于Web开发、数据分析、人工智能等领域。如何将Python改为中文?下面将为您详细介绍。 为什么要将Python改为中文? Python的英文是由…

[读论文][谷歌-12s生成] Speed is all your need

论文简要总结 刚读了下speed is all you need这个论文, https://arxiv.org/pdf/2304.11267.pdf 只是用的SD1.4没有对网络进行改造。 只做了4个改动 1 是对norm采用了groupnorm (GPU shader加速) 2 采用了GELU (GPU shader加速) 3 采用了两种attention优化,是partiti…