高性能、高可用、高并发的技术架构的常见问题
高并发、高性能、高可用
构建一个三高的系统,到底可以从哪些方面下手呢。
大概可以从以下方面入手:横向分层、纵向分割、分布式化、集群化、使用缓存、使用异步模式、使用冗余、自动化(发布、部署、监控)
具体来说,可以在不同层次常用的技术有:
前端
- 浏览器优化技术:合理布局,页面缓存,减少http请求数,页面压缩,减少 cookie 传输。
- CDN
- DNS负载均衡
- 动静分离
- 动态图片独立提供服务
- 反向代理
应用层架构
- 业务拆分
- 负载均衡
- 虚拟化服务器、容器化
- 无状态(以及分布式 Session)
- 分布式缓存
- 异步、事件驱动架构、消息队列
- 多线程
- 动态页面静态化
服务层架构
- 分布式微服务(分级管理,超时设置,异步调用,服务降级,幂等性设计)
- 同应用层架构
存储层架构
- DFS
- 关系数据库路由
- No SQL 数据库 缓存
- 数据同步
- 数据冗余
安全架构
- Web攻击(XSS、Sql Injection)
- 数据加密
- 密钥管理
发布、运维
- 自动化测试与发布
- 灰度发布
- 浏览器数据采集
- 服务器业务数据采集
- 服务器性能数据采集
- 系统监控
- 系统报警
机房
- 散热、省电、定制服务器
以上,就是建设互联网三高架构可能涉及到的知识点,比较多
互联网三高架构
高并发、高性能、高可用,简称三高(3H)
互联网应用系统开发肯定经常会看到高并发和高性能这两个词,可谓是耳熟能详,
而具体的含义和关系真的如你所想的,真正的理解了吗?
先来看一个例子:
一个蓄水池,是1m*1m*1m=1立方米大小,有一个出水口,出水口每秒钟流出0.1立方米,那么这个蓄水池的并发量是1立方米,出水速度是0.1立方米/秒。
如果增加一个出水口,都是每秒钟流出0.1立方米,那么这个蓄水池的并发量没变,但是出水速度变成了0.2立方米/秒。
同理,增大了出水口,蓄水池的出水速度也变快了。
上面我们很容易知道,并发量是一个容量的概念,性能就是出水速度,而且有下面这些结果。
- 增大蓄水池的长宽高,可以增加并发能力。
- 出水口如果扩大了出口大小,则可以提高出水的速度,也就是性能提高了。
- 增加出水口的数量,则是增加了并行处理的能力,同样可以提高性能。
那么对照我们计算机中,我们的系统中,是怎么样的结果呢?
- 增加服务器的内存大小,可以增加并发量。因为内存增加了,就可以开更多的进程,更多的线程,也可以扩大任务队列的大小。
- 提高cpu的主频速度,优化程序,可以提高性能。cpu更快了,程序优化的更好了,处理单个任务的时间也就更短了。
- 增加CPU多核甚至分布式服务器数量,也可以提高性能,同时提高并发量。
如果只是性能提高了,并发量是否也能提高呢?
如果我们静态的理解并发量,那它是不会提高的。
而我更愿意动态的来理解并发量,即:单位时间内可以进来的最大数量。
那么提高性能,是可以线性提高并发量的,因为单位时间内,进来的同时也有出去。
我们先来做一个假设:
单个进程(php fast-cgi)内存占用10M
单个线程( java web)内存占用2M
单个协程(go) 内存占用20K
队列任务(nginx) 内存占用2K
我们下面来看看内存与并发量的关系
内存量 | 进程数 | 线程数 | 协程 | 队列任务 |
---|---|---|---|---|
1G | 100 | 500 | 50K | 500K |
2G | 200 | 1000 | 100K | 1000K |
4G | 400 | 2000 | 200K | 2000K |
8G | 800 | 4000 | 400K | 4000K |
从上面的结果中,我们可以很直观的看出来,并发能力在不同的运行模式中的巨大区别。
多进程和多线程的模式,不仅是内存开销巨大,而且在数量不断增加的情况下,对CPU的压力也是非常巨大,
这也是为什么这类系统在并发量大的情况下会很不稳定,甚至宕机。
假设上边计算出来的数据,都是静态的容量,如果所有任务都不处理,那么内存肯定都是会很快就被撑爆。
所以要达到更高的并发量,就需要有更快的处理速度,即做好性能优化。
下面,再来做一个假设。
我们现在有一台服务器,配置是8核16G内存。
如果我们的应用是计算密集型,纯运算的系统,如:数据索引查询、排序等操作。
而且还要假设,这个应用在多核并行运算时不存在锁竞争的情况(只读)。
QPS = 1000ms/单个请求耗时*8
① 如果单个请求(任务)耗时100ms,那么我们可以计算出来:qps = (1000ms/100ms)*8核 = 80个/秒
② 如果我们优化处理的算法,单个请求耗时降低到10ms,那么:qps = (1000ms/10ms)*8核 = 800个/秒
③ 如果可以继续优化,将单个请求耗时降低到1ms,那么:qps = (1000ms/1ms)*8核 = 8000个/秒
上面的情况和优化的效果理解起来应该很容易,因为对服务器资源的依赖更多是CPU的运算能力和数量。
在实际的互联网应用中,系统更多是依赖 mysql,redis,rest api或者微服务,属于IO密集型。
按照上面的计算方式,可能就不太准确了,因为cpu是有富余的。
在IO阻塞的时候,开启更多任务的方式当然有上面多进程、多线程、多协程和队列的方式来实现,而且也是有效且更好地利用服务器资源的方法,可以达到更高的并发量,
毕竟我们把大部分的运算放到了应用外部的mysql,redis,rest api等服务。
到此为止,我们已经知道并发量、性能优化跟服务器资源(服务器数量,cpu,内存)的关系,也知道性能优化对并发量的影响。
解疑答惑
1、内存越多,并发量一定可以越大吗?
答:大部分情况是的。这个问题,上面有提到过,对于多进程、多线程的模式,线程太多的时候,线程抢占时间片,CPU切换上下文会越来越慢,影响系统性能。
对于协程、队列的运行模式,这个问题会好很多,当然协程调度、队列维护的开销,肯定也是会增加,只是增加的开销不至于对系统性能造成直线下降。
2、CPU越快,应用的性能一定越好吗?
答:绝对的。只不过CPU和应用性能提升可能不成线性增长的关系,因为应用可能是IO密集型,应用性能还会受到IO阻塞的影响。
3、CPU越多,应用的性能一定越好吗?
答:大部分情况是的。如果大量锁存在,性能提升可能会大打折扣,因为并行能力会被锁住,又变成单线程执行了,没有最大的发挥多CPU的作用。
4、服务器越多,并发量一定越大吗?
答:绝对的。服务器增加,CPU和内存资源相应也就越多,并发能力也就会增大,他们之间是线性相关。
5、服务器越多,性能一定越好吗?
答:大部分情况是的。但是单个服务器的效率可能会是下降的,数据一致性问题、同步问题、锁问题,这些都会导致单个服务器的效率(CPU利用率)下降,所以不是线性相关。
关于CPU利用率:
如果只是考虑应用对CPU利用效率的话:单核=多核=多服务器
单进程/单线程的系统对于服务器资源的利用率更高。
到多核的系统中,就会因为锁的问题,多任务同步的问题,操作系统调度的问题,造成一定的资源浪费。而分布式系统中,这些浪费也会更严重。
6、怎样更好的更有效的利用服务器资源呢?
答:避免因为IO阻塞让CPU闲置,导致CPU的浪费;
避免多线程间增加锁来保证同步,导致并行系统串行化;
避免创建、销毁、维护太多进程、线程,导致操作系统浪费资源在调度上;
避免分布式系统中多服务器的关联,比如:依赖同一个mysql,程序逻辑中使用分布式锁,导致瓶颈在mysql,分布式又变成串行化运算。
上面说了要避免的地方,要具体怎么来避免,到具体的业务场景就需要具体分析了。
而且有些时候,为了业务功能,或者其它方面的需求,比如:可用性、伸缩性、扩展性、安全性,不得不牺牲掉一部分性能。
总结
并发量,是一个容量的概念,服务可以接受的最大任务数量,动态的看待它,还需要把性能考虑进去。
性能,是一个速度的概念,单位时间内可以处理的任务数量。
高并发和高性能是紧密相关的,提高应用的性能,是肯定可以提高系统的并发能力的。
应用性能优化的时候,对于计算密集型和IO密集型还是有很大差别,需要分开来考虑。
增加服务器资源(CPU、内存、服务器数量),绝大部分时候是可以提高应用的并发能力和性能
前提是应用能够支持多任务并行计算,多服务器分布式计算才行,但也是要避免其中的一些问题,才可以更好的更有效率的利用服务器资源。
本文转自:互联网三高架构之高并发和高性能的理解 (CSDN)
参考推荐:
LNMP(CentOS+Nginx+Mysql+PHP)服务器环境配置
Nginx 限制单个IP的并发连接数/速度防止恶意攻击/蜘蛛爬虫采集
版权所有: 本文系米扑博客原创、转载、摘录,或修订后发表,最后更新于 2021-03-02 11:38:02
侵权处理: 本个人博客,不盈利,若侵犯了您的作品权,请联系博主删除,莫恶意,索钱财,感谢!