高可用背景介绍
高并发、高可用是互联网分布式系统架构设计中必须考虑的因素之一。
首先来说说高并发,啥是高并发,怎样才算是高并发。个人认为在衡量一个业务系统的并发能力,需要有一个维度,其中最重要的两个衡量标准是业务复杂度和硬件配置(cpu、内存、磁盘、带宽、网卡)。高并发的本质并不是一个数字这么简单,而是需要我们针对现有的业务系统再遇到高并发带来的问题时如何从架构上、设计上、编码上解决问题。微门户系统日均PV 1300W,Node端请求量日均4亿级,Java后端单个服务系统请求量日均1500W,个人认为这个量级和大多数公司相比已经很不错了。
那什么是高可用呢?简单来说就是减少系统不能提供服务的时间。一个高可用的系统需要支持服务故障自动转移、服务精准熔断降级、服务治理、服务限流、服务可回滚、服务自动扩容/缩容等能力。相比高并发,我认为高可用更重要一些。
“硬”投入
F5 VS Array
产品体系架构区别
Array操作系统是ArrayOS,使用自己编制的硬件操作系统,从稳定性来说系统不依赖于底层操作系统的稳定性。从性能来说由于使用了SpeedStack技术,相应的速度要更高。
F5的操作系统是Linux操作系统上起的应用服务(TMOS),从稳定性来说系统以来linux的稳定性。在实际应用中,相应的稳定性会差。从性能来说,采用了分层的处理,降低了数据包处理的速度。
负载均衡功能比较
Array支持L2-L7负载均衡(L4-轮询、权重、最小连接数、最快响应基于cookie、IP、Qos等会话保持算法,L7-基于cookie、IP、Qos、Header、URL、任意内容的算法),会话保持技术基于cookie、IP、Qos、ssl id、Url、Header、Hostname,服务器健康检查(ICMP、TCP/UDP、Http、Keyword、TCP/UDP Script)。
F5支持L3-L7负载均衡(L4-轮询、比率、最小连接数、最快响应、观察法、预测法,L7-需要使用IRules进行编程),会话保持技术基于cookie、IP、ssl id、SIP、Universal ID,服务器健康检查(ICMP、TCP/UDP、Http、ECV、EAV)。
域名解析服务器DNS
域名解析流程大致如下所示。
浏览器检查自身DNS缓存
操作系统缓存检查(本机)+ hosts解析(本机)
本地区域名服务器解析(LDNS)
如果在hosts文件中也没有找到对应的条目,浏览器就会发起一个DNS的系统调用,就会向本地配置的首选DNS服务器发起域名解析请求。
根域名服务器解析(Root Server)
如果LDNS没有找到对应的条目,则由运营商的DNS代我们的浏览器发起迭代DNS解析请求。它首先是会找根域的DNS的IP地址(这个DNS服务器都内置13台根域的DNS的IP地址),找到根域的DNS地址,就会向其发起请求。根域名服务器返回给本地域名服务器一个所查询域的主域名服务器(gTLD Server)地址,gTLD是国际顶级域名服务器,如.com、.cn、.org等。
主域名服务器(gTLD Server)
本地域名服务器(Local DNS Server)向gTLD服务器发送请求,接受请求的gTLD服务器查找并返回此域名对应的Name Server域名服务器的地址,这个Name Server通常就是注册的域名服务器。
管理方域名服务器(Name Server)
Name Server域名服务器会查询存储的域名和IP的映射关系表,正常情况下都根据域名得到目标IP记录,连同一个TTL值返回给DNS Server域名服务器。
软负载均衡Nginx优势
服务集群
1、通过多台计算机完成同一个工作,达到更高的效率。
2、两机或多机服务实例,工作过程等完全一样。如果一台死机,另一台可以起作用。
中间件主备、主从
主备模型
优点:简单,主备之间只有数据同步,不需要考虑别的情况。就很简单的配置一下,再搞一台服务器就能组成主备架构了。
缺点:备机等于就拿来备份,浪费了备机这台服务器的资源。上面说的不考虑别的情况指的是主机和备机它们两之间就只要复制数据,但是有些情况我们人还是得考虑主机挂了如何让备机上。
主从模型
优点:充分利用了资源,嘿嘿不想备机这么爽了,还得出来干活,对外提供读操作。而且在主机挂了的时候,如果没任命新机主之前,读操作还是能用的。
缺点:客户端需要多个判断,也就是不同操作需要发放给不同服务器。主从延迟,读操作分配给从库,就会存在数据同步的延迟问题,此时需要考虑延迟问题的一些解决办法。
双中心架构
传统主备模式
主备模式是一个业务只在一个数据中心运行,企业结合灾备等级需求和业务需求,在备份中心部署了大量的备份服务器,但备份中心仅为该业务提供灾备服务,只有当灾难发生、生产数据中心瘫痪时,灾备中心的业务系统才启动这些服务器,造成备份中心服务器资源浪费,广域网链路也无法得到充分的利用。
双中心优点
充分利用资源,避免了一个数据中心常年处于闲置状态而造成浪费。通过资源整合,“双活”数据中心的服务能力是双倍的。
双活数据中心如果断了一个数据中心,另外一个数据中心还在运行,对用户来说是不可感知的。
而一个灾备中心的模式,如果生产数据中心瘫痪,需要半个小时、甚至两个小时、甚至更长时间才能启动灾备中心,在启动灾备中心的时间里,用户交易会严重受损。
容器自动伸缩容
容器云平台提供快速部署、资源弹性伸缩等底层技术能力,通过容器云平台,可满足外部个性化应用与数字服务云平台的集成部署要求,进一步提高数字服务云平台的灵活性,改善服务水平,保障系统的快速交付和平稳运行。
- CI/CD(持续集成/持续发布)
- 弹性伸缩
- 故障隔离
- POD隔离
- 分组分流
- 自动监控
“软”设计
分层微服务化架构
1、H5前端应用提供了微信、支付宝、独立微门户等多渠道下业务功能。
2、Node端作为微门户的网关层,提供服务路由、灰度发布、用户鉴权和会话管理功能。业务高峰期,高性能的Node端服务完全可以应对高并发,静态资源通过压缩、CDN等技术降低页面加载时长,提升用户体验。
3、基础服务层是由Java编写的一系列微服务组成,CSF平台协助微服务之间的调用,缓存组件提升服务响应时间,日志组件绘制整个请求调用链,MQ组件便于业务解耦和处理并发分流。
无状态、幂等
什么是无状态?是指该服务运行的实例不会在本地存储需要持久化的数据,并且多个实例对于同一个请求响应的结果是完全一致的。无状态服务的设计便于水平扩展,提高服务可用性。
什么是幂等?就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的。一般幂等做法是防止重复提交、Token令牌、乐观锁、分布式锁、建立防重表等。
限流
流量高峰期会出现系统资源不够,不足以应对大量请求,即系统资源与访问量出现矛盾的时候,为了保证有限的资源能够正常服务,需要对系统按照预设的规则进行流量限制或功能限制。常见的限流策略如下。
1、计数器方法
系统维护一个计数器,来一个请求就加1,请求处理完成就减1,当计数器大于指定的阈值,就拒绝新的请求。
基于这个简单的方法,可以再延伸出一些高级功能,比如阈值可以不是固定值,是动态调整的。另外,还可以有多组计数器分别管理不同的服务,以保证互不影响等。
2、漏桶算法
漏桶算法其实很简单,可以粗略的认为就是注水漏水过程,往桶中以一定速率流出水,以任意速率流入水,当水超过桶流量则丢弃,因为桶容量是不变的,保证了整体的速率。
3、令牌桶方法
首先还是要基于一个队列,请求放到队列里面。但除了队列以外,还要设置一个令牌桶,另外有一个脚本以持续恒定的速度往令牌桶里面放令牌,后端处理程序每处理一个请求就必须从桶里拿出一个令牌,如果令牌拿完了,那就不能处理请求了。我们可以控制脚本放令牌的速度来达到控制后端处理的速度,以实现动态流控。
微信公众号系统使用Guava的RateLimiter对接口进行限流,其原理是令牌桶算法,也就是以固定的频率向桶中放入令牌,
熔断降级
微信公众号自助服务模块引用了Hystrix这款开源的容错系统,Hystrix能协助开发者码出强大容错能力和鲁棒性程序,具有如下优点。
- 对依赖的服务(HTTP调用、CSF服务)进行保护, 并且把控住由于依赖服务所带来的的延迟和失败
- 防止在一个复杂的分布式系统里出现级联失效(cascading failures)
- 快速失败(Fail fast),并且快速恢复依赖服务
- 优雅的降级
- 实时的监控和报警
1、隔离策略:信号量
- 隔离细度较高、CSF客户端有请求策略的设置
- 线程池隔离开销过大,还需要考隔离线程下日志同步火眼的问题
2、隔离配置:配置中心
- 省份 + 服务标识 配置隔离分组,不同分组不同的熔断、降级配置
- run(命令)调用最大的并发数 20
- fallback(降级)调用最大的并发数 15
- 熔断器半打开时间间隔 2000ms
- 10s中内最少的请求量50,大于该值,断路器配置生效
- 当出错率超过50%后熔断器启动
- 统计滚动窗口时间5s, 统计滚动窗口桶个数10
服务发现
容器云使用环境变量或DNS服务插件保证容器中程序发现Pod入口访问地址。
CSF平台针对众多业务系统相互间的服务调用,进行完整的服务生命周期治理和服务资源管控,提供系统接入,服务注册,服务申请,服务调用,日志查询等功能。
不停服发布
容器云采用一种平滑过渡的升级方式,通过逐步替换的策略,以确保不会同时关闭所有实例,保证整体系统的稳定,在初始升级的时候就可以及时发现、调整问题,以保证问题影响度不会扩大。
业务补偿机制
说到业务补偿机制,主要是解决分布式系统环境下业务数据一致性的问题,那不得不提一下两个重要的分布式理论(BASE 理论 和 CAP理论)。
1、CAP理论
- Consisteny(一致性)
一致性的要求是指,对于任何客户端来说,每次的读操作,都能获得最新的数据。即,当有客户端向A节点写入了新数据之后,其它客户端从B节点中进行读操作所获得的数据必须也是最新的,是与A节点数据保持一致的。
- Availability(可用性)
可用性的要求是指,每个请求都能在合理的时间内获得符合预期的响应(不保证获取的结果是最新的数据)。
客户端只要向A节点或B节点发起请求后,只要这两个节点收到了请求,就必须响应给客户端,但不需要保证响应的值是否正确。
- Partition tolerance(分区容错性)
分区容错性是指,当节点之间的网络出现问题之后,系统依然能正常提供服务。
CAP理论也就是说在分布式存储系统中,最多只能实现以上两点。而由于当前网络延迟故障会导致丢包等问题,所以我们分区容错性是必须实现的。也就是NoSqL数据库P肯定要有,我们只能在一致性和可用性中进行选择,没有Nosql数据库能同时保证三点。(==>AP 或者 CP)。
例如elasticsearch集群/eureka集群是基于AP的,zookeeper集群/redis集群/mongoDB集群是基于CP的。大家都知道eureka和zookeeper都可以做服务注册中心,使用dubbo作为RPC服务框架时都会用zookeeper作为服务注册中心,但是使用springcloud框架时默认都是使用eureka作为服务注册中心,对比一下eureka和zookeeper的设计原则,个人认为eureka更适合做服务注册中心。
2、BASE理论
BASE理论是对CAP理论的延伸,核心思想是即使无法做到强一致性(Strong Consistency,CAP的一致性就是强一致性),但应用可以采用适合的方式达到最终一致性(Eventual Consitency)。
BASE是指基本可用(Basically Available)、软状态( Soft State)、最终一致性( Eventual Consistency)。
3、常见补偿机制
- TCC模式(二阶段提交,Try/Confirm/Cancel)
- 异步确保,MQ异步消息,补偿表+定时任务
- 最大努力,通过通知服务器(消息通知)进行,允许失败,有补偿机制(或重发机制)
系统监控告警
为什么做监控?一个鉴权的监控系统可以是实时统计机器系统资源(CPU/内存/网络/磁盘)、查看JVM虚拟机运行情况、统计接口的调用量、统计接口耗时情况、统计接口错误异常、查看具体业务和运营节点流程。通过监控系统数据可以做系统性能告警、服务自动扩容/缩容、更早的发现服务质量问题,保证服务高可用。
为什么做告警?告警系统可以快速帮忙快速定位生产出现的问题是什么,及时通知到具体负责人。个人认为,告警系统对异常统计应该有个紧急程度(如可忽略、通知、告警),不同程度的异常通知划分到不同的责任人,通知渠道划分为短信、企业群、电话等。
微信公众号系统基于Hystrix Dashboard实现的自助服务调用监控视图
- 蓝色计数: 表示断路器打开后,直接被短路的请求数
- 黄色计数: 表示请求超时数
- 紫色计数: 表示因为线程池满而被拒绝的请求数
- 红色计数: 表示因为异常而导致失败的请求数
- 灰色百分比: 表示的是10秒内的错误率统计
- Hosts: 应用个数
- Median: Command 的中位数时间
- Mean: Command 的平均时间
- 90th/99th/99.5th: P90、P99、P99.5 时间
所有技术和百分比的统计窗口都是10秒(默认值)
总结
分布式系统中,并不是所有的业务在24小时的时间内都处于高并发状态,也可能有的业务在某一时间段处于流量高峰。面对突如其来的高并发流量,要保证系统的高可用性尤其重要。在设计高可用系统中,要从诸多方面去考虑。用大白话概括为三点,不强依赖第三方系统、自身系统健壮可靠、服务拆分不受其他服务影响。
微门户系统在高可用这方面的设计还需要继续加强,由于很多自身服务都要强依赖下游服务,保证自身服务质量尤其重要。当下游服务出现问题并且一定时间内还没有恢复,需要及时通知到开发人员,这时一套健全的监控和告警系统是必不可少的。