0%
一、服务端常用工具
- 内存kv数据库: redis
- 关系型数据库: mysql
- 集群分布式配置: etcd
二、服务端设计
1. 常用知识
1.1. 互联网三高
- 高可用: High availability
- 高拓展: High scalability
- 高性能: High efficiency
- 低延迟(响应快): low latency
- 高吞吐(高并发): high throughput
1.2. cap
1.3. 一致性
2. 注意点
- 升级
- 升级: 升级前检查脚本,升级脚本,配置备份,升级后重启,版本号修改,升级失败回退
- 降级: 支持配置回退
- 补丁: 考虑失败的回退,文件替换要有备份,可一键回退
- 定制: 同补丁
- 在线升级: 发布前最好考虑在线升级,这样出了问题可以后台出静默升级包,不需要一个一个客户去上门
- 配置
- 支持升级的配置转换,并有一条路径线,尽可能支持跨多个版本升级
- 每天备份所有重要配置,保留7天,可以及时恢复
- 集群
- 备份
- 重要数据设置备份机制,和正在使用的数据分开,失败有恢复机制
- 安全
3. 设计干货
- 多进程模块间使用redis做消息订阅机制进行传递消息,当一个模块变化,发送消息,所有订阅此消息的模块都可以受到消息做相应的操作
- 进程内部可以使用event进行消息订阅机制,一个线程或者模块改了一个东西,发送消息,订阅此消息的模块根据需要相应的改动(这里操作非事务,可能出现失败的情况)
- 后台执行命令单独提取一个进程进行,只提供接口,不允许直接拼接命令来执行,所有传入参数做防shell注入校验
- 所有接口在一个统一的地方进行参数校验,不做逻辑校验,统一一套校验机制,不需要再模块执行中做参数合法性校验,但是复杂逻辑的还需要校验
- 配置转换可以参照这个模式
- 所有配置转换脚本均要执行
- 有一个地方存放执行过哪些配置转换的脚本,执行过的不执行
- 所有执行的脚本要分为升级和降级两个步骤,这样可以直接进行降级
- 对所有接口加上权限,针对不同的角色,有不同的权限,增删改查
- 利用中间件做是否认证校验,洋葱结构,中间件进入调用,出来再次调用
- 共享内存前面预留一页4k或8k做写保护,里面可以放一些只读配置信息,防止前面踩内存导致未知问题
4. 集群形态
- 单机不可能存在完全可靠,如果保证持续可用,需要主备集群
4.1. 主备集群
- 为了追求数据可靠,主备数据基本一致,主挂掉,备机上阵
- 完全一致性: 主更新数据,要求从更新完成才返回,但是增加了风险,可能从挂掉影响主运行
- 弱一致性: 主更新数据,从节点进行异步更新数据,但是可能主从数据不一致
4.2. 分片集群
- 数据分片存储在不同的数据服务器上,也叫扩容,主备集群不叫扩容
- 但是分片集群一般会要求每个分片是一个主备集群,防止数据丢失导致整体不可用
4.3. journalnode集群
- 强一致性
- 使用相互的是否联通作为统计数据,一般认为联通是双方相互通信
- 例如,存在5台机器,其中3台相互联通,认为可以对外提供服务,另外2台相互联通认为不可以提供服务
1) 为什么集群机器数量使用奇数
- 如果存在3台,那么使用2作为可用数值,容许错误机器数为1,风险为2
- 如果存在4台,那么使用3作为可用数值,容许错误机器数为1,风险为3
- 使用偶数和奇数比并没有增加容许错误数,反而增加了风险
5. 提高系统性能
5.1. 单机
1) 提高响应时间
2) 提高吞吐量
5.2. 集群
1) 提高响应时间
2) 提高吞吐量
6. 提高系统稳定性
6.1. 几个基本点
- 所有外部调用需要设置超时时间,防止系统阻塞。包括http、rpc、thrift、kafka、redis、mysql、mongo等
- 新增加的服务需要添加兜底超时时间
- 连接池隔离,分级使用连接池,保障最核心业务的使用
- 协程使用事务,需要处理为串行执行,防止并发量大将连接池占满
- 使用异步请求或队列执行的,需要考虑对端处理不过来而队列满造成的接口阻塞情况
6.2. 几个问题实例
1) 协程启动事务造成数据库连接池占满,重要业务无法执行
- 同一时刻上报大量数据需要落库,服务端处理使用协程优化速度,并且使用了事务进行批量更新
- 由于每一个协程都使用了一个连接,事务相互之间存在竞争会卡住部分协程,造成总连接池占满,无法执行重要业务
2) 协程耗尽造成拒绝服务
- 服务端协程数量有限,对于协程使用的不合理,造成大量协程建立并卡住,最终造成服务端没有协程可用,无法对外提供服务
3) 日志服务器性能不足卡死业务服务
- 日志服务器处理队列满,造成业务服务器打印日志的接口阻塞,无法提供服务
4) 跨服务调用没有处理超时,造成阻塞
- 跨服务调用,对方挂了,调用接口没有处理超时,卡死造成业务无法访问
三、实战分析
1. 优化当前系统达到高性能
1.1. 对当前业务系统进行分析(以登陆认证为例)
- 使用并发压力工具如 locust 进行登陆注销的大并发压力测试
- 过程中进行cpu和内存消耗分析,查看具体占用资源的业务进程
- 同时开启mysql和redis的qps统计,查看过程中的qps,分析并发登陆的mysql和redis的资源消耗情况
- 查看iotop的磁盘读写情况,是否存在大量io磁盘读写
- 单个用户上线的mysql和redis的命令执行次数
- 空载和大并发用户登陆后的资源消耗情况
1) 统计图对比
- 并发压力过程中cpu消耗图
- 内存占用图
- 磁盘io占用
- 网络吞吐
- mysql的qps
- redis的qps
2) 单机统计分析优化点和性能瓶颈
- 去除mysql、redis调用、磁盘io、cpu高计算的操作查看并发登陆用户的最大值
- 添加部分mysql和redis的操作查看并发登陆用户的最大值
- 继续添加mysql和redis草最查看并发登陆用户的最大值
- 增加部分io磁盘或cpu高计算的操作查看并发登陆用户的最大值
- 如果要分析新架构语言的场景,参考上述步骤重新测试对比
- 单用户登陆过程查看执行的redis和mysql语句,分析是否存在可优化的语句
3) 集群统计分析优化点和性能瓶颈
- 大并发场景查看主从的压力分布
- 仅打主节点查看
- 仅打从节点查看,主要用于分析主节点是否会因为某些不合理操作而资源占用高
4) 几个优化思路
- 配置类主要基于缓存,对可靠性要求不高就异步落盘
- 查询类语句调用,考虑合并优化,优选redis,次选mysql
- 减少不必要的调用
- 占用cpu高的进程,考虑是否可以降低优先级
- 部分mysql查询语句考虑使用redis缓存实现
- 下发数据尽量减少不必要的数据,只下发必要数据和增量数据等
踩坑记
1. url编码
- url在请求时,除了规定的格式中的符号,参数中的符号必须要转码
- 例如get请求中的参数如果有特殊字符,需要使用一个在线转码工具转码才能上传,不然服务端解析会失败
2. 备份
微信支付
支付宝