高性能架构设计

我的架构设计专栏:https://www.nowcoder.com/creation/manager/columnDetail/0ybvLm

我的八股专栏笔记:https://www.nowcoder.com/creation/manager/columnDetail/j8ZZk0

前言

高性能和高并发,听着就有点类似,并且他们还经常一起提及,比如提高我们的并发性能,显然,高性能可以提高我们的并发,但是细化来看,他们是有区别的,他们的考量点的维度不同。高性能需要我们从单机维度到整体维度去考虑,更多的是先从编码角度、架构使用角度去让我们的单机(单实例)有更好的性能,然后再从整个系统层面来拥有更好的性能;高并发则直接是全局角度来让我们的系统在全链路下都能够抗住更多的并发请求。

高性能架构设计主要集中在单机优化、服务集群优化、编码优化三方面但架构层面的设计是高性能的基础,如果架构层面的设计没有做到高性能,仅依靠优化编码,对整体系统的提升是有限的。我们从一个全局角度来看高性能的系统设计,需要整体考虑的包括如下几个层面:

● • 前端层面。后端优化的再好,如果前端(客户端)的性能不 ok,那么对用户而言,他们的体感还是很差的,因此前端层也是有必要考虑的,只是不在我们本文的设计范围之内,在实际工作中是需要进行探讨的。

● • 编码实现层面:代码逻辑的分层、分模块、协程、资源复用(对象池,线程池等)、异步、IO 多路复用(异步非阻塞)、并发、无锁设计、设计模式等。

● • 单机架构设计层面:IO 多路复用、Reactor 和 Proactor 架构模式

● • 系统架构设计层面:架构分层、业务分模块、集群(集中式、分布式)、缓存(多级缓存、本地缓存)、消息队列(异步、削峰)

● • 基础建设层面:机房、机器、资源分配

● • 运维部署层面:容器化部署、弹性伸缩

● • 性能测试优化层面:性能压测、性能分析、性能优化

1. 前端层面

后端优化的再好,如果前端(客户端)的性能不 ok,那么对用户而言,他们的体感还是很差的,因此前端层也是有必要考虑的,只是不在我们本文的设计范围之内,在实际工作中是需要进行探讨的。

这里简单说明下,从我个人工作的经历来看,前端(客户端)这里可以优化的点包括但不限于:数据预加载、数据本地缓存、业务逻辑前置处理、CDN 加速、请求压缩、异步处理、合并请求、长连接、静态资源等

CDN加速

当我们的系统中存在着大量的静态资源请求:

对于移动 APP 来说,这些静态资源主要是图片、视频和流媒体信息;

对于 Web 网站来说,则包括了 JavaScript 文件、CSS 文件、静态 HTML 文件等等。

最常用的静态资源加速手段就是采用CDN。

CDN加速是一种网络技术,旨在通过分布式网络节点将内容快速、高效地分发给用户。

CDN加速的核心价值在于提高用户访问网站或应用时的速度和体验。它通过全球分布的服务器网络来缓存内容,将数据存储在用户附近的地理位置,从而缩短数据传输距离和时间。使用CDN可以减少网站的加载时间,提高用户的满意度和留存率。

2. 编码实现层面

批量处理

无论是读请求或者写请求,如果接口支持批量查询或者批量写操作,都可以减少RPC调用的次数,减少网络开销,从而优化整体的性能,所以在提供接口的时候一般要考虑提供可以批量查询或者批量写入的接口。

无锁设计(lock free)

在多线程、多协程的框架下,如果我们并发的线程(协程)之间访问共享资源,那么需要特别注意,要么通过加锁、要么通过无锁化设计,否则没有任何处理的访问共享资源会产生意想不到的结果。而加锁的设计,在并发较大的时候,如果锁的力度不合适,或者频繁的加锁解锁,又会使我们的性能严重下降。

为此,在追求高性能的时候,大家就比较推崇无锁化的设计。目前很多后台底层设计,为了避免共享资源的竞争,都采用了无锁化设计,特别是在底层框架上。无锁化主要有两种实现,无锁队列和原子操作。

● • 无锁队列。可以通过 链表或者 RingBuffer(循环数组)来实现无锁队列。

● • 原子操作。利用硬件同步原语 CAS 来实现各种无锁的数据结构。比如 Go 语言中的 atomic 包、C++11 语言中的 atomic 库。

数据序列化

为什么要说 数据序列化协议?因为我们的系统,要么就是各个后端微服务之间通过 RPC 做交互,要么就是通过 HTTP/TCP 协议和前端(终端)做交互,因此不可避免的需要我们进行网络数据传输。而数据,只有序列化后,才方便进行网络传输。

序列化就是将数据结构或对象转换成二进制串的过程,也就是编码的过程,序列化后,会把数据转换为二进制串,然后可以进行网络传输;反序列化就是在序列化过程中所生成的二进制串转换成数据结构或者对象的过程,将二进制转换为对象后业务才好进行后续的逻辑处理。

常见的序列化协议如下

● • Protocol Buffer(PB)

● • JSON

● • XML

● • 内置类型(如 java 语言就有 java.io.Serializable)

常见的序列化协议的对比在网上有各种性能的对比,这里就不在贴相关截图了,只说结论:从性能上和使用广泛度上来看,后端服务之间现在一般推荐使用 PB。如果和前端交互,由于 HTTP 协议只能支持 JSON,因此一般只能 JSON。

池化技术(资源复用)

池化技术是非常常见的一个提高性能的技术,池化的核心思想就是对资源进行复用,减少重复创建销毁所带来的开销。复用就是创建一个池子,然后再在这个池子里面对各种资源进行统一分配和调度,不是创建后就释放,而是统一放到池子里面来复用,这样可以减少重复创建和销毁,从而提高性能。而这个资源就包括我们编程中常见到如 线程资源、网络连接资源、内存资源,具体到对应的池化技术层面就是 线程池(协程池)、连接池、内存池等。

● • 线程池(协程池)。本质都是进程、线程、协程这些维度的一个池子,先创建合适数量的线程(协程)并且初始处于休眠状态,然后当需要用到的时候,从池子里面唤醒一个,然后执行业务逻辑,处理完业务逻辑后,资源并不释放,而是直接放回池子里面休眠,等待后续的请求被唤醒,这样重复利用。

○ • 创建线程的开销是很大的,因此如果来一个请求就频创建一个线程、进程,那么请求的性能肯定不会太高。

● • 连接池。这个是最常用的,一般我们都要操作 MySQL、Redis 等存储资源,同样的,我们并不是每次请求 MySQL、Redis 等存储的时候就新创建一个连接去访问数据,而是初始化的时候就创建合适数量的连接放到池子里面,当需要连接去访问数据的时候,从池子里面获取一个空闲的连接去访问数据,访问完了之后不释放连接,而是放回池子里面。

○ • 连接池需要保证连接的可用性,就是这个连接和 MySQL、Redis 等存储是必须要定期发送数据来保证连接的,要不然会被断开。同时我们要针对已经失效(断开)的连接进行检测和摘除。

● • 内存池。常规的情况下,我们都是直接调用 new、malloc 等 Linux 操作系统的 API 来申请分配内存,而每次申请的内存块的大小不定,所以,当我们频繁 分配内存、回收内存的时候,会造成大量的内存碎片,同时每次使用内存都要重新分配也会降低性能。内存池就是先预先分配足够大的一块内存,当做我们的内存池,然后每次用户请求分配内存的时候,就会返回内存池中的一块空闲的内存,并将这块内存的标志置为已使用,当内存使用完毕释放内存的时候,也不是真正地调用 free 或 delete 来释放内存,而是把这块内存直接放回内存池内并且同时把标志置为空闲。一般业内都有相关的套件来帮我们来做这个事情,比如在 C/C++ 语言里面,都有相关库去封装原生的 malloc,glibc 实现了一个 ptmalloc 库,Google 实现了一个 tcmalloc 库。

● • 对象池。其实前面几种类型的池化技术,其实都可以作为对象池的各种应用,因为各种资源都可以当做一个对象。对象池就是避免大量创建同一个类型的对象,从而进行池化,保证对象的可复用性。

异步化

对于处理耗时的任务,如果采用同步等待的方式,会严重降低系统的吞吐量,可以通过异步化进行解决。特别是对非关键依赖模块进行异步化处理,可以大大的提升系统的并行处理能力和系统吞吐量。而异步化最常用的方案是采用消息队列,无论是本地的消息队列或者消息队列组件都是异步化处理的常用方案,特别对于提高写入性能具有比较明显的作用。

并发流程

如果一个任务需要处理多个子任务,可以将没有依赖关系的子任务并发化,这种场景在后台开发很常见。如一个请求需要查询3个数据,分别耗时T1、T2、T3,如果串行调用总耗时T=T1+T2+T3。对三个任务执行并发,总耗时T=max(T1,T 2,T3)。该方案无论读写请求都适用。

3. 单机架构设计层面

单机优化层面就是要尽量提升单机的性能,将单机的性能发挥到极致的其中一个关键点就是我们服务器采取的并发模型,然后在这个模型下,去设计好我们的服务器对连接的管理、对请求的处理流程。而这些就涉及到我们的多协程、多线程的进程模型和异步非阻塞、同步非阻塞的 IO 模型。

在具体实现细节上,针对连接的管理,要想提高性能,那么就要采用 IO 多路复用技术,可以参考I/O Multiplexing查看,I/O 多路复用技术的两个关键点在于:

● • 当多条连接共用一

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

架构设计学习专栏 文章被收录于专栏

不想当架构师的后端开发工程师不是好码农! 此专栏用于存放我的架构设计学习笔记,内容一部分源于网上资料,一部分源于gpt和我自己的理解。建议喜欢本专栏的盆友尽早订阅。欢迎给本专栏的文章点赞、评论!

全部评论
觉得本文有用的欢迎评论,订阅本专栏
点赞 回复 分享
发布于 07-15 23:38 湖北
觉得文章有用的欢迎动动byd小手点个赞,你的赞对我很重要!
点赞 回复 分享
发布于 07-18 22:57 湖北

相关推荐

4 12 评论
分享
牛客网
牛客企业服务