服务网格ServiceMesh和高并发、高可用设计手段

凉夜lrs

关注

阅读 58

2022-08-26

前言

承接上文 ​​互联网架构演进之路​​

1、ServiceMesh架构设计
2、高可用设计手段
3、高并发设计手段

先推荐大家一个很好用的画软件设计图的工具

gitmind

此图仅仅为了展示使用gitmind画出来效果 请忽略内容

简洁、清晰、有效

服务网格ServiceMesh和高并发、高可用设计手段_数据

​正文开始​

ServiceMesh架构设计

​公共业务逻辑下沉​

服务网格ServiceMesh和高并发、高可用设计手段_应用程序_02

业务程序不关注通讯组件
通过jar包的方式引入
基础设施组件升级困难

服务网格ServiceMesh和高并发、高可用设计手段_缓存_03

服务组件版本升级
要让业务组在jar包中替换
影响基础设施团队的交付能力和交付速度

服务网格ServiceMesh和高并发、高可用设计手段_数据_04

多编程语言之间 通信 问题
每种语言都要写一套基础设施 成本大
因为通讯组件和应用程序耦合在一起

业务研发团队和基础设施团队务必物理解耦

一套基础实施支持多语言开发
应用程序可以多种语言
基础设施能力从应用程序中下沉成为一个单独的进程

​服务网格​

1、独立进程
2、服务之间通讯
3、不管有状态服务还是无状态服务未来一定跑在云原生(docker k8s)上
4、轻量级网络代理
5、与应用程序部署在一起 对应用程序透明

​服务网格架构​

服务网格ServiceMesh和高并发、高可用设计手段_应用程序_05

sidecar 是一个 rpc服务

应用程序A->sidecarA->sidecarB->应用程序B
反向同理

通讯协议两两都是tcp
数据协议 pb

不管应用程序是什么语言 只有一套sidecar就行了

服务升级不依赖业务团队
业务团队迭代速度快

​为什么必须部署在一起​

同一个物理机或k8s pod
基于 tcp 轻量级
不需要考虑负载均衡\重试\服务注册\配置中心\路由

​最早期ServiceMesh​

服务网格ServiceMesh和高并发、高可用设计手段_应用程序_06

​案例1-百度空间​

服务网格ServiceMesh和高并发、高可用设计手段_缓存_07

用的是pull模式

百度空间 数据量大 数据一致性没那么高 是异步架构

服务网格ServiceMesh和高并发、高可用设计手段_应用程序_08

​案例2-社交IM​

服务网格ServiceMesh和高并发、高可用设计手段_缓存_09

pc桌面版 tcp长连接

web用不了tcp长连接
http协议模拟 长轮询

类似直播 难点 抗同时并发量

同步架构 消息实时性

服务网格ServiceMesh和高并发、高可用设计手段_应用程序_10

路由层是IM特有的 不需要关注

​水平方向拆分​

服务网格ServiceMesh和高并发、高可用设计手段_缓存_11

最开始的时候
业务简单 人少 业务都放在一个进程 好维护
粒度粗

​垂直方向拆分​

服务网格ServiceMesh和高并发、高可用设计手段_应用程序_12

公共逻辑层 

1、组件化 jar包
2、服务化 下沉为独立服务 提供兼容接口

​继续水平拆分​

服务网格ServiceMesh和高并发、高可用设计手段_数据_13

互联网核心技术实践

1、高可用设计手段
2、高并发设计手段(从架构、代码、算法)
3、服务无状态化(高可用其中一个手段之一)
4、负载均衡 (常用的负载均衡算法 更多广义角度阐述)
5、服务幂等性(依赖于分布式锁)
a 请求重复执行多次 服务保证最终结果完全一致
b 业务 库存只剩一个 多个用户同时抢购 保证商品不超卖
c 用户下单 用户没有结束之前 不允许重复下单
d 消息发到mq 发了多次 下游消费保证消息去重
6、分布式事务
7、服务降级 限流 熔断
8、灰度发布
9、服务全链路压测

高可用设计

​硬件总是会有生命周期​

1、
x86 32cpu 128内存 万兆 1T硬盘 一台5万左右
基本上使用3年

宕机和服务器台数相关 台数越多宕机可能性越大

2、
分布式 CAP

单机CA不存在 没有网络划分

AP和CP更多 机房多个硬盘 网络发生划分 机器还可不可用

​软件总会有Bug​

​评价维度​

  • 不科学(因流量有低峰和高峰)

一年/一季度/一月 停机时间占比
99表示365*24*60*1%=88小时

1个9是90%
365*24*60*90%=1/10 880个小时

  • 科学

停机时间影响的总的请求量/总的请求量

​冗余 部署多份​

服务部署在不同的机柜和不同机架

无状态化(完全对等)可以快速扩容 弹性缩容

比如两台机器 每一台都是全量的session数据 不是无状态的

如果一台服务挂了 重启 session没了 就不对等了

​负载均衡​

网关->业务逻辑层1和业务逻辑层2

过程:

若业务逻辑层1挂了
负载均衡组件会知道1挂了
踢掉1
转移到2上
恢复1

异步是高并发手段也是高可用手段

不太关心返回结果
不是请求的关键路由

核心流量同步 非核心异步

不仅仅服务层面高可用
数据层面也要高可用

​服务实时监控​

服务网格ServiceMesh和高并发、高可用设计手段_数据_14

实时监控 实现逻辑:

基于日志来做
5秒记录一个日志
耗时打在日志记录上
写在本地磁盘
通过flume 数据采集
发送到kafaka消息队列
然后spark实时统计实时耗时

​服务分级-降低和避免服务出现故障​

服务网格ServiceMesh和高并发、高可用设计手段_应用程序_15

​如何无缝停止线上服务​

目标:停机对用户没有伤害
即如果接受了你的请求 我100%处理完

在网关层面拒绝掉

​网关热切换功能​

热开关切换

比如8点停机
8点过来的请求都处理完
8点之后的请求 开关从0变1 所有请求都拒绝

​8点前的请求保证什么时候处理完?​

1、不优雅:每层打不打日志 如果打印日志这一层还在处理
2、优雅:前端请求 有超时时间
若超时时间5秒
则8点05秒的时候 超时

关机从上层往下层停止服务

​不具备热开关​

机器防火墙配置在某一个时间点只出不进

​请求流程​

服务网格ServiceMesh和高并发、高可用设计手段_应用程序_16

高并发设计

缩短延迟
提高吞吐量
让系统处于合理状态

服务网格ServiceMesh和高并发、高可用设计手段_缓存_17

​空间换时间​

缓存数据库数据
因数据库比内存昂贵

​时间换空间​

网络传输 http通讯 gz压缩 解压会消耗cpu时间

​变更次数少的数据​

1、app页面上购物分类 一级 手机 二级电脑
变更少 不能每次登陆就拉取一次
通过版本号判断 哪些更新了 只有更新了才会下载

2、好友数 每次登陆的时候拉一次 变化不频繁
列表数据有一个版本号 server端和客户端都放一个
判断版本号有没有更新 若有则拉一次

​哪些请求的耗时很大​

1、一个服务集群若有4万QPS
对于占90%流量的前5接口进行优化

剩下的qps也不能忽略 若是慢查询 也不行

2、查看一个服务调用了多少rpc请求
若数据、算法等核心的同步化

非核心流程异步执行
拆分到单独模块去执行 比如消息队列

3、一个逻辑调用多个RPC接口
接口之间没有数据依赖 可以考虑并行调用

​优化层次​

服务网格ServiceMesh和高并发、高可用设计手段_缓存_18

​代码层面​

1、不要循环遍历rpc请求
而应该调用批量接口组装数据

2、避免生成过多无用对象 比如使用isDebugEnabled() 应直接log.debug()

3、ArrayList HashMap初始化容量设置是否合理
扩容代价很大
比如根据业务量实际情况直接初始化大小100万 虽然耗费点内存 但性能可以保证

4、rpc接口查询出来的数据复用

5、复制一份数据 直接修改
读多写少的情况 用CopyOnWriteArrayList

6、StringBuilder的容量在预分配的情况下 性能比String提升15倍左右

7、是否正确初始化数据 全局共享数据 饿汉式模式
即在用户访问前先初始化好

​数据库​

1、状态值 若长度在255以内 用unsigned tinyint ; ip使用int而非varchar

2、使用enum的场景 使用tinyint替换 因enum扩展需要改表

3、禁止select * 会耗费 io、内存、cpu、网络

4、分析查询场景建立合适的索引
分析字段的可选择性、索引长度、对长的varchar使用前缀索引

5、字段 Not Null

允许Null字段需要额外的存储空间去处理Null
并且很难优化

目的是降低服务器CPU使用率、IO流量、内存占用、网络消耗、降低响应时间

​局部性原理​

服务网格ServiceMesh和高并发、高可用设计手段_应用程序_19

这是个二维数组 在内存中是一维数组

第一段 耗时 140ms
第二段 耗时 2700ms

服务网格ServiceMesh和高并发、高可用设计手段_缓存_20

越靠近CUP越快

1、速度越来越高 内存->L3->L2->L1多级缓存

2、在内存是一个大的一维数组
二维数组在内存中按行排列
先存放a[0]行 再放a[1]行

3、按行遍历:局部性原理 Cache Hit(缓存命中率高)

4、按列遍历:下一列和上一列的数组元素在内存中并不是连续的
很可能导致Cache Miss(缓存未命中)

5、CPU需要去内存载入数据 速度较CPU L1 Cache的速度降低了很多
(主存 100ns L1 Cache 0.5ns)

6、能用缓存就用缓存 无论是本地缓存还是分布式缓存

7、高频访问 时效性不高 适合缓存 比如 广告位
时效性很高 需要考虑缓存一致性问题 不适合用缓存 比较交易数据

​代码逻辑要适应数据变化的场景​

服务网格ServiceMesh和高并发、高可用设计手段_缓存_21

1、explain:SQL的执行计划
2、prossible_keys idx_addtime
key null 表示没有索引

查询数据量一旦超过30% 不会走索引 全表扫描

​报表查询​

只计算增量数据和之前计算结果合并

​并发和锁优化​

基于CAS LockFee(读不需要加锁 写加锁)比mentex(读写都要加锁)性能要好

​案例1-电商秒杀系统​

服务网格ServiceMesh和高并发、高可用设计手段_应用程序_22

数据分层次校验
上层尽量过滤无效请求
可以是不精确过滤
层层限流 最后一层做数据一致性校验 扣减库存

漏斗模式

服务网格ServiceMesh和高并发、高可用设计手段_数据_23

1、静态数据 Html js css静态文件 放CDN 缓存到用户端(APP/浏览器)

2、非实时动态数据 缓存在靠近用户访问链路的位置(商品标题、商品描述、用户是否有秒杀资格、秒杀是否已结束)

3、实时数据:营销数据(红包、折扣)商品库存数 过滤掉用户

​如何保证不超卖​

DB事务保证一致性

服务网格ServiceMesh和高并发、高可用设计手段_数据_24

​案例2-Feed系统​

服务网格ServiceMesh和高并发、高可用设计手段_数据_25

热点数据缓存到调用链路更靠近用户的地方

服务网格ServiceMesh和高并发、高可用设计手段_缓存_26

1、内存存储最活跃的数据

2、L1缓存容量小负责抗最热点的数据
L2缓存考虑目标是容量 缓存更大范围数据
一般一般用户的timeline
高热点数据单独缓存 比如设置白名单 大V的用户数据单独缓存

3、feed 前3页 97% 前面几页数据作为热点数据缓存到L1 cache

4、业务逻辑层往往也会开一些缓存来存热点数据 比如大V的id

服务网格ServiceMesh和高并发、高可用设计手段_缓存_27

​push模式​

若push 那只推活跃用户
比如1万个用户 在业务逻辑层 每批100个用户需要推送
100个线程并行推

从策略上优化

先推活跃用户

​如何区分活跃用户?​

活跃用户列表 长度100万
用户已上线就在列表中写一下 下线删除

​微博数据存储解决方案​

服务网格ServiceMesh和高并发、高可用设计手段_应用程序_28

1、Pika Key-Value 固化存储(持久化存储)
2、对象存储 Ceph\FastDFS

​微信朋友圈是推拉结合​

1、发现 有消息提醒 是推
2、点开朋友圈是拉

​微博最新数据展示逻辑​

比如你有500个好友 拿每个人的100个数据 共5万条数据 在业务逻辑层按照timeline倒序排列

​websocket和长轮询本质上没区别​

websocket底层也是长轮询
web上用不了tcp协议
websocket在http基础上封装了长轮询

后记

接下来会继续分享 服务网格ServiceMesh相关的实践 

觉着有用的话 点个再看哈😄


精彩评论(0)

0 0 举报