‘高并发&高性能&高可用服务程序’编写及运维指南

博观而约取,厚积而薄发。这篇文章主要讲述‘高并发&高性能&高可用服务程序’编写及运维指南相关的知识,希望能为你提供帮助。
导言:
记得在远2012年时,因为向往着能写高并发程序,自己选择了跳槽。开始时是写支撑数万设备并发的程序(我们物联网设备业务需要保持长连接),随着企业的发展,逐渐增长到十万、数十万设备,当时还讲究挖掘单机性能,所以紧着各种线程模型、I/O模型……不断地挖掘潜能,实在挖不动了就开始着手用分布式方案的解决。比如当时开源的一个高性能服务模型:< https://github.com/yaocoder/HPNetServer>
 
后来,有幸在这家集团公司开启了内部创业生涯,主导创立运营了一个服务大百万用户的互联网平台级产品,也多多实践了高并发& 高性能& 高可用服务的编写和运维。
 
再后来,出去北京参与创业和自己创业了几年,失败后就又回到曾经的公司,这时这个平台已经有千万级用户,百万日活了。但是因为人员的陆续调整,曾经负责高并发& 高性能服务的有经验的同事陆续去了北京一线大厂,此时的研发团队对于如何编写运维高并发& 高性能& 高可用服务经验有限,于是几个月前我结合自己的实践经验和其他业界高手的知识分享编写了这样的指导手册,希望能给予团队这样的指导:找问题、定目标、做实践。
 
还有,在写这份手册前,又把十年前反复阅读实践的一本书《构建高性能Web站点》重新阅读了一遍,虽然技术在更新迭代,但优秀的书籍和思想永远不会老,年龄焦虑中的我也希望我们每一个曾经的程序员不会老,或者社会和公司不会嫌弃我们老。致青春永在!
一、找问题 1. 对平台业务的了解
平台业务现状决定着服务的特点,如平台的有效用户量/设备量,业务平峰期、业务高峰期、业务低谷期的情况
2. 对衡量系统性能数据指标的了解
实际工作中发现很多后台同事对基本的性能衡量指标缺乏了解,无法评估系统的性能水平。
图 MeterSphere压测报告
:::
3. 对技术框架、技术组件的了解
实际工作中发现很多同事对所采用的技术框架、技术组件仅仅限于了解和基本应用,但掌握不透彻,应用有限,无法发挥其有效价值。
4. 对技术原理的了解
浅尝辄止是做好技术工作的大忌,如果对技术原理缺乏了解,造成潜在问题的同时,出现问题无法快速定位问题。
5. 系统的全局观
涵盖系统开发、系统测试、服务治理、运维保障
6. 技术债务情况
业务复杂度、数据复杂度、技术复杂度
二、定目标系统的目标:高性能、高可用、高扩展
1. 高性能

  • 性能体现了系统的并行处理能力,也就是前面提到Throughput(吞吐量)指标。在有限的服务器资源投入下,并行处理能力的提高也就意味着成本的降低。
  • 性能体现了系统的响应能力,也就是前面提到的RT(响应时间)指标。响应时间越短用户的体验越好,也就意味着用户价值的提升。 2. 高可用
  • 可用性表示系统可以正常提供服务的时间,高可用体现了系统具有较高的无故障运行能力。
可用度 9的个数 年停机时间(分钟) 适用产品 备注
0.999 三个9 500(8.8天) 一般服务器 测试环境,不能用于生产环境
0.9999 四个9 50 企业级服务 生产环境最低要求
0.99999 五个9 5 一般电信级服务 大型商城级等应用
0.999999 六个9 0.5 更高要求电信级服务 金融级服务器
3. 高扩展
  • 表示系统的扩展能力,流量高峰期需要在短时间内且不中断现有服务的情况下完成扩容,平滑稳定地承接峰值流量。
  • 高扩展性需要考虑:自身的应用服务集群,数据库、缓存、消息队列等中间件,云服务器、带宽、负载均衡器等第三方依赖。当并发量级提升至某个临界点,上述每一个都可能成为扩展的瓶颈点。
三、做实践 1. 高性能的实践方案
1.1 缓存
  • 多级缓存:使用CDN、本地缓存、分布式缓存等缓存静态数据或更新频率低的动态数据。同时注意对缓存场景中的热点key、缓存雪崩(缓存穿透、缓存击穿、缓存并发)造成的数据一致性等问题的处理。
  • 缓存预热:通过异步任务提前预热数据到本地缓存或者分布式缓存中。
  • 预计算:比如非实时个性化推荐场景,可以提前计算好的推荐页面缓存起来,用户登录时直接获取。 1.2 数据库
  • 关系型数据库的分库分表和索引优化。
  • 借助搜索引擎技术(如Elasticsearch)解决复杂查询问题。
  • 选用新型高性能分布式数据库的使用,比如HBase、 ClickHouse等。 1.3 流量治理
  • 集群部署,通过负载均衡机制进行自动缩扩容,减少单服务压力。
  • 对流量进行削峰填谷,通过MQ(消息队列)承接流量。 1.4 程序及架构
  • 并发处理,通过多线程将串行逻辑并行化。
  • 异步化,将次要流程通过多线程、MQ、甚至延时任务进行异步处理。
  • 减少IO次数,比如数据库和缓存的批量读写、RPC的批量接口调用。
  • 减少网络传输或IO时的数据包大小,包括采用轻量级的通信协议、合适的数据结构、减少缓存key的大小、压缩缓存value等。
  • 各种池化技术的使用,池大小的合理设置,包括HTTP请求池、线程池(考虑CPU密集型还是IO密集型设置核心参数)、数据库和Redis连接池等。
  • 程序逻辑优化,采用更高效的算法。
  • 锁选择,读多写少的场景用乐观锁,或者考虑通过更小颗粒度分段锁的方式减少锁冲突。
  • JVM优化,GC算法的选择等,尽可能减少GC频率和耗时。
2. 高可用的实践方案
2.1 服务及流量治理
  • 对于无状态服务:当前节点出现故障时迅速利用负载均衡组件或服务治理框架切换至另一个可用节点。
  • 对于有状态服务:采用主备或者热备方案实施故障节点切换。比如mysql的主从切换、Redis的哨兵与Cluster集群模式、MongoDB的副本集模式与Sharding 模式。
  • 接口层面:合理的超时设置、重试策略和幂等设计。
  • 服务熔断降级:为保证核心服务高可用,可牺牲非核心服务,在必要时进行熔断处理。
  • 限流处理:对超过系统处理能力的请求直接拒绝或者返回错误码。
  • MQ(消息队列):消息可靠性保证,包括producer端的重试机制、broker侧的持久化、consumer端的ack机制等。
2.2 运维及监控
  • 故障注入与灾备演练:刻意制造系统故障,测试系统高可用能力。
  • 降低发布风险:蓝绿部署、滚动部署、金丝雀(灰度)发布。
  • 监控告警:搭建基础设施和服务应用级别全方位的监控和告警体系,如CPU、内存、磁盘、网络的监控告警,以及Web服务器、JVM、数据库、各类中间件的监控告警和业务应用指标的监控告警。
3. 高扩展的实践方案
3.1 业务层的拆分:微服务架构 3.1.1 以领域驱动设计(DDD)来进行业务维度的微服务拆分
  1. 业务中台领域建模
    根据流程或功能边界,初步划分子域边界,并将子域分为通用子域和核心子域。在子域内开展事件风暴,找出界限上下文边界,完成领域建模。
  2. 业务单元化设计
    以领域建模为基准进行单元化设计,向上建设微前端实现领域模型的前端页面逻辑,向下建设微服务实现领域模型的领域逻辑。将微服务和微前端组合为业务单元,完成集成、测试和部署。
  3. 构建企业级前台应用
    根据企业级业务流程,组合和编排不同业务单元的微前端页面,实现不同业务单元的业务能力在企业级前台的业务联通和融合。
  4. 中台和后台的解耦
    采用领域事件驱动机制实现中台微服务之间,以及中台与后台之间业务逻辑的解耦,实现数据的融合。
    3.1.2 微服务合理的分层架构
    ‘高并发&高性能&高可用服务程序’编写及运维指南

    文章图片

    ::: hljs-center
图 微服务分层架构
:::
3.1.3 微服务框架(生态)的选择Dubbo、Spring Cloud、K8s + Service Mesh的对比
  • 技术实践对比
              Dubbo SpringCloud K8s + ServiceMesh
服务发现和LB ZK/Nacos + client Eureka + Ribbon K8s service
API网关 N/A Zuul/Spring Cloud Gateway Ingress Gateway
配置管理 Diamond/Nacos Spring Cloud Config ConfigMaps/Secrets
熔断限流 Sentinel Hystrix HealthCheck/Probe/ServiceMesh
日志监控 ELK ELK EFK
Metrics监控 Dubbo Admin/Monitor Actuator/MicroMeter+Promethus Heapster+Promethus
调用链监控 N/A Spring Cloud Sleuth/Zipkin Jaeger/Zipkin
应用打包 Jar/War Uber Jar/War Docker Image/Helm
服务语言框架 Dubbo RPC + java Spring(Boot)REST + Java 框架、语言无关
发布和调度 N/A N/A kube-Scheduler
自动伸缩和自愈 N/A N/A kube-Scheduler/AutoScaler
进程隔离 N/A N/A Docker/Pod
环境管理 N/A N/A Namespace/Authorization
资源配置 N/A N/A CPU/Mem limit,Namespace Quotas
流量治理 N/A N/A ServiceMesh
  • 生态优劣势对比
      Dubbo SpringCloud K8s + ServiceMesh
优势 阿里背书,成熟稳定,RPC高性能,流量治理方面较细致 Netflix/Pivotal背书,社区活跃,开发体验好,抽象和组件化好 谷歌、CNCF背书,抽象和组件化好,微服务生态统一且完整,支持异构语言,社区活跃
不足 技术较老、更新慢,SDK的耦合度高,仅支持Java技术栈,社区活跃度较低 仅支持Java技术栈,运行耗资源 技术门槛较高,ServiceMesh的sidecar机制有一定的性能损耗
3.2 数据层的拆分【‘高并发&高性能&高可用服务程序’编写及运维指南】按照业务维度做垂直拆分,按照数据特征维度做水平拆分(分库分表)
4. 扩展实践:云原生技术体系

    推荐阅读