免费注册,打造高效身份管理
博客/开发者/Authing 实践|亿级流量系统架构的演进之路(建议收藏)
Authing 实践|亿级流量系统架构的演进之路(建议收藏)
Authing 官方2021.08.12阅读 789

随着人们数字化生活方式的改变,网络用户越多,对我们系统的考验就越大,如何承载高并发是整个行业都在思考的一件事情。我们来看一下生活中常见的高并发场景:


· 电商秒杀,大量用户同时在系统上进行抢购

· 12306 抢票,春节回家车票紧张,我们都会持续刷票或者使用抢票软件

· 银行交易系统,所有线上源源不断的交易(部分线下交易)都需要经过银行交易系统

 

高并发系统,也就是我们常说的三高系统:高并发,高性能,高可用。面向此类的三高系统,我们关注的属性是性能、可用性、伸缩性、扩展性、安全性,架构模式应该具有分布式化,集群化,自动化,异步化等特点的。

 

很多公司在初期时,都是单体应用的架构模式,单体应用的优点如下:


· 容易部署:这个不容置疑,整个项目就一个 war 包,部署特别方便。

· 容易运行/测试:这个也类似,我们在测试阶段只需要启动一个 war 包即可。


但是相比优点,这种架构缺点更加明显:


· 复杂性高:随着业务的不断迭代,项目的代码量会急剧的增多,项目模块也会随着而增加,模块与模块之间的关系就会变成的很复杂,整个项目就会变成的非常复杂,在新增和修改代码的时候都会做很多的测试,很容易会由于一处的变动影响之前业务的功能。

· 部署频率低:随便代码的增多,首先部署会越来越消耗时间,还有我们在修复一个很小很小的 bug 的时候整个项目都要重新部署,所以我们会集中一个时间点部署多个需求。

· 可靠性差:这个很容易理解,假如某个影响出现了死循环,导致内存溢出,会影响整个项目挂掉。

· 扩展性差:我们在新增业务的时候,代码层面会考虑在不影响现有的业务基础上编写代码,提高了代码的复杂性。


#01 


在单体应用架构模式不能满足我们需求的时候,下一步往往不是直接拆分应用,考虑到成本问题,会先进行应用内部优化。为了提升性能我们会做代码优化,使用池化技术,比如线程池,连接池等,将热点数据缓存,包括一些算法上的优化。


优化做好之后,随着业务的发展,遇到性能问题,下一步就是服务化拆分。那么服务化拆分具体该如何实施呢?


一个最有效的手段就是将不同的功能模块服务化,独立部署和运维。这种服务化拆分方式一种是纵向拆分,是从业务维度进行拆分。标准是按照业务的关联程度来决定,关联比较密切的业务适合拆分为一个微服务,而功能相对比较独立的业务适合单独拆分为一个微服务。还有一种服务化拆分方式是横向拆分,是从公共且独立功能维度拆分。标准是按照是否有公共的被多个其他服务调用,且依赖的资源独立不与其他业务耦合。


#02 


对系统架构做了比较大的改造,我们此时需要了解系统的性能怎么样,如何较为准确的知道性能呢,那就需要对系统进行压测。


说到压测,先介绍一下木桶理论。木桶理论又称短板理论,其核心思想是一只木桶盛水多少,并不取决于最高的木板,而取决于最短的那块木板。我们在压测时,也要找到系统的短板所在。


一个完整的压测闭环:压测目标、压测环境、压测模型、发现问题、解决问题、验证结果,这个闭环可能会重复,直到达成我们的压测目标。


那我们需要关注哪些指标呢?资源上一般要关注 CPU、内存、网络、I/O、数据库等,性能指标主要关注:QPS、TPS、RT、并发数、吞吐量、成功率、GC 等。实现指标监控的数据来源就是日志,我们可以按结果导向在各个服务上输出日志通过 ELK 来实现抽取并查看日志,并通过 Grafana 来实现监控的目的。


#03


服务化拆分完成后,随着流量的增长,单机部署的 MySQL,会导致 I/O 频率过高,数据库就会成为下一个短板,此时我们就需要对数据库进行优化。优化思路主要有以下几种:


· 主从复制,读写分离。单机 MySQL,读写都在一台MySQL上面完成,性能肯定不高。如果有三台 MySQL,一台 mater 只负责写操作,两台 salve 只负责读操作,性能就大大提高。

· 数量量达到千万级以后,主从架构可能还是不太合适,只能对读数据库进行扩展,无法对写进行扩展,写基本上还是集中在 master 中。所以我们还是需要减少单表的记录条数,进而减少数据查询的时间,提高吞吐量,也就是我们说的分表。

· 分表能解决单表数据量太大的问题, 但是无法解决数据库的并发处理能力,我们可以通过对一个关键字对分库数量取模的方式,对数据访问进行数据库的路由。

· 分库分表:既可以解决单表海量数据的问题, 又可以提高数据库的并发处理能力。


#04


当我们了解了整个系统的并发性能后,为了保障服务的高可用性,我们需要针对服务进行限流,熔断,降级等操作。限流可以使用拒绝策略和流量整形策略,需要根据业务场景来选择使用,常用的限流算法有计算器,漏桶,令牌桶等。


在微服务架构中,一个请求需要调用多个服务是非常常见的。如客户端访问 A 服务,而 A 服务需要调用 B 服务,B 服务需要调用 C 服务,由于网络原因或者自身的原因,如果 B 服务或者 C 服务不能及时响应,A 服务将处于阻塞状态,直到 B 服务 C 服务响应。此时若有大量的请求涌入,容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,造成连锁反应,会对整个微服务系统造成灾难性的严重后果。此时我们就需要对系统进行熔断和降级。


熔断就像保险丝,当某一个服务节点出现失败和超时达到一定的频率时,我们就需要让调用能够快速失败,而非阻塞调用,从而避免对其他的服务造成级联反应。


服务降级的策略有很多,以下列举部分常用方案:


· 页面降级:可视化界面禁用点击按钮、调整静态页面

· 延迟服务:如定时任务延迟处理、消息入MQ后延迟处理

· 写降级:直接禁止相关写操作的服务请求

· 读降级:直接禁止相关读的服务请求

· 缓存降级:使用缓存方式来降级部分读频繁的服务接口

· 停服务:关闭不重要的功能,为核心服务让出资源

 

要做到高可用,除了上述的策略还不够,当我们的量级上升后,还需做到异地多活等,如两地三中心,达到容灾效果。比如在多个地点分别建立一个机房,上层通过 DNS 会根据一定规则代理到较近的机房,当某机房出现故障或者升级时,其他机房也可以继续承载业务,达到业务不间断的效果。

文章作者

avatar

Authing 官方

0

文章总数

authing blog rqcode
关注 Authing 公众号
随时随地发现更多内容
authing blog rqcode
添加 Authing 小助手
加入 Authing 开发者大家庭