一、交易型系统设计的一些原则
1.在设计系统时,应该多思考墨菲定律:
* 任何事情都没有表面看起来那么简单
* 所有的事都会比你预计的时间长
* 可能出错的事总会出错
* 如果你担心某种情况发生,那么它就更有可能发生
2.系统划分时,要思考康威定律:
* 系统架构是公司组织架构的反映
* 应该按照业务闭环进行系统拆分/组织架构划分,实现闭环/高内聚/低耦合,减少沟通成本
* 如果沟通出现问题,那么就应该考虑进行系统和组织架构的调整
* 在合适时机进行系统拆分,不要一开始就把系统/服务拆得非常细,虽然闭环,但是每个人维护的系统多,维护成本高
3.在有限资源的情况下,一定是先解决当下最核心的问题,预测并发现未来可能出现的问题,一步步解决最痛点的问题,即满足需求的系统是不断迭代优化出来的
A.高并发原则
1.无状态:比较容易进行水平扩展,应用无状态,配置文件有状态
2.拆分:在系统设计初期,是做一个大而全的系统还是按功能模块拆分系统,这个需要根据环境进行权衡
* 系统维度:按照系统功能/业务拆分
* 功能维度:对一个系统进行功能再拆分
* 读写维度:根据读写比例特征进行拆分
* AOP维度:根据访问特征,按照AOP进行拆分
* 模块维度:按照基础或者代码维护特征进行拆分
3.服务化
* 判断是不是只需要简单的单点远程服务调用,单机不行集群是不是就可以解决?在客户端注册多台机器并使用Nginx进行负载均衡是不是就可以解决?随着调用方越来越多,应该考虑使用服务自动注册和发现(Dubbo使用ZooKeeper)
* 考虑服务的分组/隔离
* 后期随着调用量的增加还要考虑服务的限流、黑白名单等
* 进程内服务->单机远程服务->集群手动注册服务->自动注册和发现服务->服务的分组/隔离/路由->服务治理如限流/黑白名单
4.消息队列
* 用来解耦一些不需要同步调用的服务或者订阅一些自己系统关心的变化
* 可以实现服务解耦(一对多消费)、异步处理、流量削峰/缓冲等
* 要注意处理生产消息失败,以及消息重复接收时的场景
* 大流量缓冲(电商大促等),牺牲强一致性,而保证最终一致性,需要考虑并发处理和重复处理的问题
* 在使用了消息异步机制的场景下,可能存在消息的丢失,需要考虑进行数据校对和修正来保证数据的一致性和完整性
5.数据异构
* 对订单表进行异构,异构一套用户订单表,按照用户ID进行分库分表,还需要考虑对历史订单数据进行归档处理
* 数据闭环如商品详情页,通过如MQ机制接收数据变更,然后原子化存储到合适的存储引擎,如Redis或持久化KV存储;使用数据聚合,前端就可以一个调用拿到所有数据,一般存储在KV存储中;前端通过一次或少量几次调用拿到所需要的数据;
* 如果一次需要多个数据,可以考虑使用Hash Tag机制将相关的数据聚合到一个实例
6.缓存银弹
* 浏览器缓存:设置请求过期时间,如对响应头Expires、Cache-control进行控制,适用于对实时性不太敏感的数据
* APP客户端缓存:一般会在大促之前把APP需要访问的一些素材提前下发到客户端进行缓存
* CDN缓存:将页面、活动页、图片推送到离用户最近的CDN节点,要考虑URL的设计
* 接入层缓存:考虑使用如Nginx搭建一层接入层,URL重写、一致性哈希、proxy_cache、proxy_cache_lock、shared_dict
* 应用层缓存:Redis等
* 分布式缓存:Redis集群
7.并发化
B.高可用原则
1.降级
* 开关集中化管理:通过推送机制把开关推送到各个应用
* 可降级的多级读服务:比如服务调用降级为只读本地缓存、只读分布式缓存、只读默认降级数据
* 开关前置化:如架构是Nginx->Tomcat,可以将开关前置到Nginx接入层
* 业务降级:把一些同步调用改成异步调用,优先处理高优先级数据或特殊特征的数据
2.限流
* 恶意请求流量只访问到cache
* 对于穿透到后端应用的流量可以考虑使用Nginx的limit模块处理
* 对于恶意IP可以使用nginx deny进行屏蔽
3.切流量
* DNS:切换机房入口
* HttpDNS:主要APP场景下,在客户端分配好流量入口,绕过运营商LocalDNS并实现更精准流量调度
* LVS/HaProxy:切换故障的Nginx接入层
4.可回滚:版本化
C.业务设计原则
1.防重设计:考虑防重key、防重表
2.幂等设计:在重复消息消费时进行幂等处理
3.流程可定义
4.状态与状态机:正向状态(付款、发货)和逆向状态(取消、退款)应该根据系统和特征来决定要不要分离存储,状态设计时应有状态轨迹,方便跟踪当前订单的轨迹并记录相关日志,还有订单状态的变迁以及并发状态修改问题
5.后台系统操作可反馈:需要考虑效果的可预览,可反馈
6.后台系统审批化:对于有些重要的后台功能需要设计审批流,并记录日志,从而保证操作可追溯、可审计
7.文档和注释:在一个系统发展的一开始就应该有文档库(设计架构、设计思想、数据字典/业务流程、现有问题),业务代码和特殊需求都要有注释
8.备份:代码备份和人员备份
二、负载均衡与反向代理
1.外网DNS应该用来实现用GSLB(全局负载均衡)进行流量调度,如将用户分配到离他最近的服务器上以提升体验
2.对于内网DNS,可以实现简单的轮询负载均衡,但会有一定的缓存时间并且没有失败重试机制,我们可以考虑选择如HaProxy和Nginx
3.Nginx一用于七层负载,其吞吐量是有一定限制的,为了提升整体吞吐,会在DNS和Nginx之间引入接入层,如使用LVS、F5可以做四层负载均衡,即首先DNS解析到LVS/F5、然后LVS/F5转发给Nginx,再由Nginx转发给后端RealServer
4.Nginx目前提供了HTTP(ngx_http_upstreamm_module)七层负载均衡,1.9.0版本支持TCP(ngx_stream_upstream_module)四层负载均衡
5.二层负载均衡是通过改写报文的目标MAC地址为上游服务器MAC地址,源IP地址和目标IP地址是没有变的,负载均衡服务器和真实服务器共享同一个VIP,如LVS DR工作模式
6.四层负载均衡是根据端口将报文转发到上游服务器(不同的IP地址+端口),如LVS NAT模式、HaProxy
7.七层负载均衡是根据端口号和应用层协议如HTTP协议的主机名、URL,转发报文到上游服务器(不同的IP地址+端口),如HaProxy、Nginx
A.upstream配置
1.在http指令下配置upstream即可
2.主要配置:
* IP地址和端口
* 权重:默认是1,越高分配给这台服务器的请求就越多
B.负载均衡算法
1.用来解决用户请求到来时如何选择upstream server进行处理,默认采用的是round-robin(轮询),同时支持ip_hash
2.hash key [consistent],对某个key进行哈希或者使用一致性哈希算法进行负载均衡,建议考虑使用一致性哈希算法
3.least_conn,将请求均衡到最少活跃连接的上游服务器
C.失败重试
1.主要两部分配置:
* upstream server:server xxxx:80 max_fails=2 fail_timeout=10s weight=1;...
* proxy_pass:配置proxy_next_upstream相关配置,proxy_next_upstream、proxy_next_upstream_timeout、proxy_next_upstream_tries
D.健康检查
1.nginx对上游服务器的健康检查默认采用的是惰性策略
2.TCP心跳检查:check interval=3000 rise=1 fall=3 timeout=2000 type=tcp;
3.HTTP心跳检查:
* check_http_send "HEAD /status HTTP/1.0\r\n\r\n";
* check_http_expect_alive http_2xx http_3xx;
3.使用的是opensresty模块,安装nginx之前需要先打nginx_upstream_check_module补丁
E.其他配置
1.备份上游服务器,backup
2.不可用上游服务器,down
F.长连接
1.可以通过keepalive指令配置长连接数量
G.HTTP反向代理
1.反向代理除了实现负载均衡之外,还提供如缓存来减少上游服务器的压力
2.还可以开启gzip压缩,减少网络传输的数据包大小
H.HTTP动态负载均衡
1.Consul是一款开源的分布式服务注册与发瑞系统,通过HTTP API可以使得服务注册、发现实现起来非常简单
2.Consul+Consul-template
2.Consul+OpenResty
I.Nginx四层负载均衡
1.静态负载均衡
* 启用ngx_stream_core_module,安装Nginx时,添加--with-stream
* 配置在stream指令下
* 可配置数据库连接
2.动态负载均衡
* nginx-upsync-module,提升了HTTP七层动态负载均衡,动态更新上游服务器不需要reload nginx
三、隔离术
1.隔离是指将系统或资源分割开,系统隔离是为了在系统发生故障时,能限定传播范围和影响范围,即发生故障后不会出现滚雪球效应,从而保证只有出问题的服务不可用,其他服务还是可用的
2.资源隔离通过隔离来减少资源竞争,保障服务间的相互不影响和可用性
A.线程隔离
1.主要是指线程池隔离,在实际使用时,我们会把请求分类,然后交给不同的线程池处理
B.进程隔离
1.在公司发展初期,一般是先从零到一,不会一上来就进行系统拆分,这样就会开发出一些大而全的系统,系统中的一个模块/功能出现问题,整个系统就不可用了
2.通过将系统拆分为多个子系统来实现物理隔离,通过进程隔离使得某一个子系统出现问题时不会影响到其他子系统
C.集群隔离
1.随着系统的发展,单实例服务无法满足需求,此时需要服务化技术,通过部署多个服务形成服务集群,来提升系统容量
D.机房隔离
1.随着对系统可用性的要求,会进行多机房部署,每个机房的服务都有自己的服务分组,本机房的服务应该只调用本机房服务,不进行跨机房调用
2.当一个机房服务发生问题时,可以通过DNS/负载均衡将请求全部切到另一个机房,或者考虑服务能自动重试其他机房的服务
3.一种办法是根据IP(不同机房IP段不一样)自动分组,还有一种较灵活的办是通过在分组名中加上机房名
E.读写隔离
1.通过主从模式将读和写集群分离
F.动静隔离
1.将动态内容和静态资源分离,将静态资源放在CDN上
G.爬虫隔离
1.爬虫和正常流量的比例能达到5:1,甚至更高,一种解决办法是通过限流解决,另一种解决办法是在负载均衡层面将爬虫路由到单独集群,Nginx即可配置
2.使用OpenResty,不仅对爬虫user-agent过滤,还会过滤一些恶意IP ,可以考虑IP+Cookie的方式
H.资源隔离
1.最常见的资源,如磁盘、CPU、网络,这些宝贵的资源,都会存在竞争问题
I.使用Hystrix实现隔离
1.Hystrix是Netflix开源的一款针对分布式系统的延迟和容错库,目的是用来隔离分布式服务故障
2.提供线程和信号量隔离,以减少不同服务之间资源竞争带来的相互影响:提供优雅降级机制;提供熔断机制使得服务可以快速失败,而不是一直阻塞等待服务响应,并能从中快速恢复
3.解决的问题:
* 限制调用分布式服务的资源使用,某一个调用的服务出现问题不会影响其他服务调用,通过线程池隔离和信号量隔离实现
* 提供了优雅降级机制:超时降级、资源不足时(线程或信号量)降级,降级后可以配合降级接口返回拖底数据
* 提供了熔断器实现,当失败率达到阈值自动触发降级(如因网络故障/超时造成的失败率高),熔断器触发的快速失败会进行快速恢复
* 提供了请求缓存、请求合并实现
J.基于Servlet3实现请求隔离
四、限流详解
1.限流的目的是通过对并发访问/请求进行限速或者一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务(定向到错误页或告知资源没有了)、排队或等待(比如秒杀、评论、下单)、降级(返回兜底数据或默认数据)
2.在压测时我们能找出每个系统的处理峰值,然后通过设定峰值阈值,来防止系统过载时,通过拒绝处理过载的请求来保障系统可用,另外,也应根据系统的吞吐量、响应时间、可用率来动态调整限流阈值
3.常见的限流有
限制总并发数(比如数据库连接池、线程池)
限制瞬时并发数(如Nginx的limit_conn模块)
限制时间窗口内的平均速率(如Guava的RateLimiter、Nginx的limit_req模块,用来限制每秒的平均速率)
限制远程接口调用速率
限制MQ的消费速率
还可以根据网络连接数、网络流量、CPU或内存负载来限流
4.缓存目的是提升系统访问速度和增大系统处理能力,可谓是抗高并发的银弹。降级是当服务出问题或者影响到核心流程的性能,需要暂时屏蔽掉,待高峰过去或者问题解决后再打开的场景
A.限流算法
1.令牌桶算法:是一个存放固定容量令牌的桶,按照固定速率往桶里添加令牌
2.漏桶算法:漏桶作为计量工具(The Leaky Bucket Algorithm as a Meter)时,可以用于流量整形(Traffic Shaping)和流量控制(Traffic Policing)
B.应用级限流
1.限流总资源数:可以使用池化技术,如连接池、线程池
2.限流总并发/连接/请求数:Tomcat配置、MySQL(max_connections)、Redis(tcp-backlog)
3.限流某个接口的总并发/请求数:Java的AtomicLong或Semaphore
C.分布式限流
1.Redis+Lua
2.Nginx+Lua
D.接入层限流
1.接入层通常指请求流量的入口,该层的主要目的有:负载均衡、非法请求过滤、请求聚合、缓存、降级、限流、A/B测试、服务质量监控等
2.ngx_http_limit_conn_module,limit_conn是对某个key对应的总的网络连接数进行限流,可以按照IP来限制IP维度的总连接数,或者按照服务域名来限制某个域名的总连接数,只有被Nginx处理的且已经读取了整个请求头的请求连接才会被计数器统计
3.ngx_http_limit_req_module,limit_req是漏桶算法实现,用于对指定key对应的请求进行限流,比如按照IP维度限制请求速率
4.lua-resty-limit-traffic,OpenResty了Lua限流模块,可以按照更复杂的业务逻辑进行动态限流处理,提供了limit.conn和limit.req实现
E.节流
1.我们想在特定埋单窗口内对重复的相同事件最多只处理一次,或者想限制多个连续相同事件最小执行时间间隔,可使用节流(Throttle)实现,其防止多个相同事件连续重复执行,主要有:throttleFirst、throttleLast、throttleWithTimeout
2.throttleFirst/throttleLast
* 是指在一个时间窗口内,如果有重复的多个相同事件要处理,则只处理第一个或最后一个,其相当于一个事件频率控制器,把一段时间内重复的多个相同事件变为一个,减少事件处理频频率,从而减少无用处理
* 前端开发可以使用jquery-throttle-debounce-plugin实现
* Android开发可以使用RxAndroid实现
3.throttleWithTimeout
* 也叫作debounce(去抖),限制两个连续事件的先后执行时间不得小于某个时间窗口
* 当两个连续事件的时间间隔小于最小间隔时间窗口,就会丢弃上一个事件,而如果最后一个事件等待了最小间隔时间窗口后还没有新的事件到来,那么会处理最后一个事件
* 可用于搜索关键词自动补全等功能
五、降级特技
1.当访问量剧增、服务出现问题(如响应时间长或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级
2.降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如购物车、结算)。降级也需要根据系统的吞吐量、响应时间、可用率等条件进行手工降级或自动降级
A.降级预案
1.参考日志级别设置预案
* 一般:有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级
* 警告:有些服务在一段时间内成功率有波动,可以自动降级或人工降级并发送警告
* 错误:可用率低于90%,或数据库连接池用完了,或访问量突然猛增到系统能承受的最大阈值
* 严重错误:因为特殊原因数据出现错误,需要紧急人工降级
2.降级按照是否自动化可分为:自动开关降级和人工开关降级
3.降级按照功能可分为:读服务降级和写服务降级
4.降级按照处于系统层次可分为:多级降级
5.降级的功能点主要从服务器端链路考虑,即根据用户访问的服务调用链路来梳理哪里需要降级
* 页面降级
* 页面片段降级
* 页面异步请求降级
* 服务功能降级
* 读降级:如多级缓存模式,如果后端服务有问题,则可以降级为只读缓存,适用于对读一致性要求不高的场景
* 写降级:秒杀抢购,可以只进行Cache的更新,然后异步扣减库存到DB,保证最终一致性即可,此时可以将DB降级为Cache
* 爬虫降级:大促活动时,可以将爬虫流量导向静态页或者返回空数据,从而保护后端稀缺资源
* 风控降级:抢购/秒杀等业务,完全可以识别机器人、用户画像或者根据用户风控级别进行降级处理,直接拒绝高风险用户
B.自动开关降级
1.超时降级
* 当访问的数据库/HTTP服务/远程调用响应慢或者长时间响应慢,且该服务不是核心服务的话,可以在超时后自动降级
* 如果是调用别人的远程服务,则可以和对方定义一个服务响应最大时间,如果超时了,则自动降级
* 在实际场景中一定要配置好超时时间和超时重试次数及机制
2.统计失败次数降级:当失败调用次数达到一定阈值自动降级(熔断器),然后通过异步线程去探测服务是否恢复了
3.故障降级:要调用的远程服务挂掉了,则可以直接降级,降级后的处理方案:默认值(比如库存挂了返回默认) 、兜底数据(比如广告挂了返回提前准备好的静态页面)、缓存
4.限流降级:当达到限流阈值时,后续请求会被降级,降级后的处理方案:排队页面、无货、错误页
C.人工开关降级
1.开关可以存放到配置文件、数据库、Redis/ZooKeeper,可以定期同步开关数据,然后通过判断某个KEY的值来决定是否降级
2.对于新开发的服务进行灰度测试,就需要设置开关,还有多机房服务,也可以通过开关完成
3.还有一引起是因为功能问题需要暂时屏蔽掉某些功能
D.读服务降级
1.一般采取的策略有:暂时切换读(降级到读缓存、降级走静态化)、暂时屏蔽读(屏蔽读入口、屏蔽某个读服务)
2.我们会在接入层、应用层设置开关,当分布式缓存、RPC服务/DB有问题时自动降级为不调用,适用于读一致性要求不高的场景
3.页面降级、页面片段降级、页面异步请求降级都是读服务降级,目的是丢卒保帅
4.动态化降级为静态化
5.静态化降级为动态化
E.写服务降级
1.大多数场景下是不可降级的,不过可以:将同步操作转换为异步操作、限制写的量/比例(如评论开关量大时不可见)
F.多级降级
1.降级是离用户走越近越对系统保护得好,因为业务的复杂性导致越到后端QPS/TPS越低
* 页面JS降级开关:控制页面功能降级
* 接入层降级开关:控制请求入口的降级
* 应用层降级开关:控制业务的降级
G.配置中心
1.应用层API封装
2.使用配置文件实现开关配置
3.使用配置中心实现开关配置:ZooKeeper、Diamond、Disconf、Etcd 3、Consul
H.使用Hystrix实现降级
I.使用Hystrix实现熔断
六、超时与重试机制
A.简介
1.如果应用不设置超时,则可能会导致请求响应慢,慢请求累积导致连锁反应,甚至造成应用雪崩
2.读服务天然适合重试,而写服务大多不能重试(如果写服务是幂等的,则重试是允许的),重试次数太多会导致多倍请求流量
3.在进行代码Review时,一定记得Review超时与重试机制
4.超时与重试机制:
* 代理层超时与重试
* Web容器超时
* 中间件客户端超时与重试
* 数据库客户端超时
* NoSQL客户端超时
* 业务超时
* 前端Ajax超时
B.代理层超时与重试
1.Nginx
* client_header_timeout time:设置读取客户端请求头超时时间,默认为60s,响应408,如果在些超时时间内客户端没有发送完请求头
* client_body_timeout time:设置读取客户端内容体超时时间,默认为60s,响应408,两次成功读操作间隔时间,而不是发送整个请求体超时时间
* send_timeout_time:设置发送响应到客户端的超时时间,默认60s,两次成功写操作间隔时间,而不是发送整个响应的超时时间
* keepalive_timeout timeout [header_timeout]:设置HTTP长连接超时时间,要配合keepalive_disable和keepalive_requests一起使用
2.DNS解析超时设置
* resolver_timeout 30s:设置DNS解析超时时间,默认30s,配合resolver address ... [valid=time]进行DNS域名解析
3.代理超时设置
* proxy_connect_timeout time:与后端/上游服务器建立连接的超时时间
* proxy_read_timeout time:设置从后端/上游服务器读取响应的超时时间
* proxy_send_timeout time:设置往后端/上游服务器发送请求的超时时间
* proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | non_idempotent | off ...:配置什么情况下需要请求下一台上游服务器进行重试ZXCV
* proxy_next_upstream_tries number:设置重试次数,指所有请求次数,默认0表示不限制
* proxy_next_upstream_timeout time:设置重试最大超时时间,默认0表示不限制
* upstream存活超时,max_fails和fail_timeout:配置什么时候Nginx将上游服务器认定为不可用/不存活
4.Twemproxy:Twitter开源的Redis和Memcache代理中间件,减少与后端缓存服务器的连接数
C.Web容器超时
D.中间件客户端超时与重试
1.JSF是京东自研的SOA框架,主要有三个组件:注册中心、服务提供端、服务消费端
2.JMQ是京东消息中间件,主要有四个组件:注册中心、Broker(JMQ的服务器端实例,生产和消费消息都跟它交互)、生产者、消费者
E.数据库客户端超时
F.NoSQL客户端超时
G.业务超时
1.任务型:可以通过Worker定期扫描数据库修改状态,有时需要远程服务超时了,可以考虑使用队列或者暂时记录到本地稍后重试
2.服务调用型:可以简单地使用Futrue来解决问题(Java)
H.前端Ajax超时
1.可以在请求时带上timeout参数
2.使用setTimeout进行超时重试
七、回滚机制
A.事务回滚
1.对于单库事务回滚直接使用相关SQL即可
2.分布式事务常见的如两阶段提交、三阶段提交协议,可以考虑事务表、消息队列、补偿机制(执行/回滚)、TCC模式(预占/确认/取消)、Sagas模式(拆分事务+补偿机制)等实现最终一致性
B.代码库回滚
1.SVN、Git等
C.部署版本回滚
1.部署版本化:发布时采用全量发布,避免增量发布
2.小版本增量发布:先发布1台验证,没问题发布10台,最后全部发布
3.大版本灰度发布:两个版本并行跑一段时间
4.架构升级并发发布:通过A/B方式慢慢地将流量引入到新版本集群,如果新版本出现大面积故障,降级回老版本
D.数据版本回滚
1.两种思路:全量和增量
* 全量版本化是指即使只变更了其中一个字段也将整体记录进行历史版本化
* 增量版本化是只保存变化的字段
八、压测与预案
A.系统压测
1.压测一般指性能压力测试,用来评估系统的稳定性和性能,从而决定是否需要扩容或缩容
2.压测之前要有压测方案【如压测接口、并发量、压测策略(突发、逐步加压、并发量)、压测指标(机器)】,之后要产出压测报告【压测方案、机器负载、QPS/TPS、响应时间(平均、最小、最大)、成功率、相关参数(JVM参数、压缩参数)】,最后根据压测报告分析的结果进行系统优化和容灾
3.线下压测:通过如JMeter、Apache ab压测系统的某个接口或者某个组件
4.线上压测:按读写分为读压测、写压测和混合压测,按数据仿真度分为仿真压测和引流压测,按是否给用户提供服务分为隔离集群压测和线上集群压测
5.读压测是压测系统的读流量,写压测是辱没系统的写流量,读和写是会相互影响 的,因此,这种情况下要进行混合压测
6.仿真压测是通过模拟请求进行系统压测,数据可以是使用程序构造、人工构造,或者使用Nginx访问日志
7.隔离集群压测是指将对外提供服务的部分服务器从线上集群摘除,然后将线上流量引流到该集群进行压测,这种方式很安全
8.单机压测是指对集群中的一台机器进行压测,从而评估出单机极限处理能力,发现单机的瓶颈点,这样可以把单机性能优化到极致
9.离散压测,即选择的数据应该是分散的或者长尾的
10.全链路压测
B.系统优化和容灾
1.拿到压测报告 后,接下来会分析报告,然后进行一些有针对性的优化,如硬件升级、系统扩容、参数调优、代码优化、架构优化
2.在进行系统优化时,要进行代码走查,发现不合理的参数配置,如超时时间、降级策略、缓存时间等,在系统压测中进行慢查询排查,包括Redis、MySQL等,通过优化查询解决慢查询问题
3.在应用系统扩容方面,可以根据去年流量、与运营业务方沟通促销力度、最近一段时间的流量来评估出是否需要进行扩容,需要扩容多少倍
4.在扩容时要考虑系统容灾,比如分组部署、跨机房部署,容灾是通过部署多组(单机房/多机房)相同应用系统,当其中一组出现问题时,可以切换到另一个分组
C.应急预案
1.系统分级:可以按照交易核心系统和交易支撑系统进行划分
2.针对核心系统进行全链路分析,从用户入口到后端存储,梳理出各个关键路径,对相关路径进行评估并制定预案
* 网络接入层:由系统工程师负责,关注机房不可用、DNS故障、VIP故障等预案处理
* 应用接入层:由开发工程师负责,关注上游应用路由切换、限流、降级、隔离等预案处理
* Web应用层和服务层:由开发工程师负责,关注依赖服务的路由切换、连接池(数据库、线程池等)异常、限流、超时降级、服务异常降级、应用负载异常、数据库故障切换、缓存故障切换等
* 数据层:由开发工程师或系统工程师负责,关注数据库/缓存负载高、数据库/缓存故障等
3.制定好预案后,应对预案进行演习,来验证预案的正确性,在制定预案时也要设定故障的恢复时间
4.要对关联路径实施监控报警,包括服务器监控(CPU使用率、磁盘使用每户、网络带宽等)、系统监控(系统存活、URL状态/内容监控、端口存活等)、JVM监控(堆内存、GC次数、线程数等)、接口监控【接口调用量(每秒/每分钟)、接口性能(TOP50/TOP99/TOP999)、接口可用率等】,然后配置报警策略如监控时间段、报警阈值、通知方式