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

前言

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

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

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

gitmind

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

简洁、清晰、有效

正文开始

ServiceMesh架构设计

公共业务逻辑下沉

业务程序不关注通讯组件
通过jar包的方式引入
基础设施组件升级困难
服务组件版本升级
要让业务组在jar包中替换
影响基础设施团队的交付能力和交付速度
多编程语言之间 通信 问题
每种语言都要写一套基础设施 成本大
因为通讯组件和应用程序耦合在一起

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

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

服务网格

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

服务网格架构

sidecar 是一个 rpc服务

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

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

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

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

为什么必须部署在一起

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

最早期ServiceMesh

案例1-百度空间

用的是pull模式

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

案例2-社交IM

pc桌面版 tcp长连接

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

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

同步架构 消息实时性
路由层是IM特有的 不需要关注

水平方向拆分

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

垂直方向拆分

公共逻辑层 

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


继续水平拆分

互联网核心技术实践

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

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

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

核心流量同步 非核心异步

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

服务实时监控

实时监控 实现逻辑:

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

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

如何无缝停止线上服务

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

在网关层面拒绝掉

网关热切换功能

热开关切换

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

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

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

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

不具备热开关

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

请求流程

高并发设计

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

空间换时间

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

时间换空间

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

变更次数少的数据

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

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

哪些请求的耗时很大

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

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

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

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

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

优化层次

代码层面

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流量、内存占用、网络消耗、降低响应时间

局部性原理

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

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

越靠近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、高频访问 时效性不高 适合缓存 比如 广告位
   时效性很高 需要考虑缓存一致性问题 不适合用缓存 比较交易数据

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

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

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

报表查询

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

并发和锁优化

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

案例1-电商秒杀系统

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

漏斗模式

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

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

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

如何保证不超卖

DB事务保证一致性

案例2-Feed系统

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

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

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

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

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

push模式

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

从策略上优化

先推活跃用户

如何区分活跃用户?

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

微博数据存储解决方案

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

微信朋友圈是推拉结合

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

微博最新数据展示逻辑

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

websocket和长轮询本质上没区别

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

后记

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

觉着有用的话 点个再看哈😄
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值