如何构建高可用的分布式系统


在公司做了一次高可用的分享,由于keynote的内容为大纲,特此加点注释说明,分享给大家,水平有限,欢迎拍砖~~


分布式服务要素

        

分布式服务主要考虑如下几点:


  • 性能


    扫描二维码关注公众号,回复: 3181334 查看本文章

主要考虑指标: 响应时间,并发数,吞吐量

常用的手段

  • 压缩,对传输数据进行压缩(类似合并js,压缩图片,减少cookie传输等前端手段),服务间传递序列化的算法

  • CDN,内容分发网络,本质为缓存,将数据缓存在离用户最近的地方,该服务一般由第三方供应商提供,应尽量避免回源

  • 分布式缓存,memcached,redis

  • 异步解耦,消息队列

  • 资源复用,连接池,线程池

  • 集群,避免单机负载过大

  • 存储,ssd,ssd与机械硬盘的区别

  • 查询优化,sql优化,搜索引擎

  • 高可用

减少系统不可用的时间,作为基础服务组需要优先考虑系统的高可用,本次主题,稍后详解


  • 伸缩

可以通过添加/减少服务器提高/降低服务的处理能力,无状态的服务便于实现,主要靠各层次的负载均衡


  • 可拓展

在对现有系统影响较小的情况下,系统功能可持续拓展、提升的能力

  • 对业务进行拆分,遵循开闭原则,明确各业务边界,例如将消息网管拆分为push,sms,email,如果揉合在一块对功能拓展时影响较大

  • 服务间使用Restapi,各api引入版本的概念,高版本api兼容低版本api,在拓展时不影响老业务

  • 消息队列,消息解耦,不同业务按需订阅对应消息,例如usercenter发布用户注册消息,积分服务订阅消息给新用户赠送积分,邮件服务订阅消息给用户发送邮件,如新增一个为新用户赠送还款金的服务,只需要订阅消息即可


  • 安全

  • 参数加签,例如使用阿里聚安全

  • 加密算法,消息摘要,对称加密,非对称加密

  • https,CA

  • 服务调用鉴权,openid,jwt


大纲


高可用

高可用的目标一般以n个9来表示,如4个9表示99.99% ,一年365*24*(1-99.99%) = 8.76 ,表示系统一年不可用时间不超过8.76个小时

一般通过服务冗余加上故障转移来实现应用的高可用,规避单点


一个用户请求流程一般由图(不是所有的应用都这样,不同的公司架构存在差异)

客户端到反向代理


  • 通过硬件F5实现硬负载,一台费用大概几十万,稳定可靠

  • nginx实现软负载,nginx是高性能的HTTP和反向代理服务器,

    nginx.conf,可以配置权重等额外参数


一般采用keepalived+vip实现nginx的高可用

域名通过dns解析得到ip,通过ARP(Address Resolution Protocol,地址解析协议,根据IP地址获取物理地址的一个TCP/IP协议)列表获取对应服务的mac地址,从而访问对应服务,通过vip对外提供服务,vip对应的mac地址为主节点的mac地址,备节点通过keepalived来检测主节点是否可用,如不可用会广播消息,使得vip对应的mac地址替换为备节点的mac地址


同城双活

通过nginx也可以实现针对域名访问的接口实现同城多活,如果采用服务发现的方式需要存在多数据中心,能跨数据中心实现服务发现

upstream test {
server 10.0.40.126:80 max_fails=1 fail_timeout=30s;
server 10.0.40.124:80 backup;
}


Gateway & Services


Gateway也可以理解为一个微服务,因此统一讨论


负载均衡

实现软负载均衡,核心有三点:

  • 服务发现,发现依赖服务的列表

  • 服务选择规则,在多个服务中如何选择一个有效服务

  • 服务检测,检测失效的服务,高效剔除失效服务

ribbon为典型的案例

服务发现与注册

consul,zk,dubbo

  • consul是一个集服务发现与注册、配置、健康检查、多数据中心的工具

  • zookeeper是分布式应用程序协调服务,类Unix文件系统路径的层级结构,通过临时节点+监听可以实现丰富的功能

  • dubbo是功能丰富分布式服务框架,服务治理,国内应用广泛

服务发现是采用推还是拉?

当有节点在服务注册中心加入/移除时,注册中心需要主动将消息推给该节点对应的Client端

优点:

服务端的请求压力小,只有在服务变更时需要推送消息

缺点:

该模式下每个服务需要和注册中心维护一个长连接,定时心跳,fd默认为1024,最大65535,需要使用nio多路复用,实现技术上比较复杂 


各服务节点主动去注册中心轮询,通过定时任务去实现

优点:

实现简单,适合服务数量较少的情况

缺点:

每个服务都在定时的轮询,注册中心压力大,为降低注册中心的压力,可以考虑若干服务通过一个agent去请求注册中心,整个集群中由若干个agent去注册中心请求,consul就可以实现类似的方式

服务选择

在获取调用服务列表以后最终调用哪个服务呢? 这就需要进行服务的选择,常见的做法有如下几种:

  • 轮询

  • 加权轮询

  • 随机

  • 最少连接

  • ip进行hash

  • 动态权重

在我所在公司实际应用中各服务机器性能都差不多,一般采用轮询的方式,轮询实现起来简单,但不适合各机器性能不一致的情况

动态权重用的也比较频繁

在Client端记录各服务的权重,初始服务权重为100,每成功请求一次后权重加1,但不超过100,每失败一次权重减10,权重最小为0,在连续失败几次以后为防止客户端的请求压垮服务端,可考虑间隔若干时间不分配请求到该服务,如果权重为0,可以考虑间隔一定时间释放一个请求过去看看服务是否恢复

服务检测

服务检测一般为定时的异步任务,可以简单采用ping、pong的方式检测服务是否存活,如果服务失效,则从服务列表中剔除

服务检测一般有以下集中方式:

  • 向注册中心发起请求检测

  • Client直连服务端检测

在spring-boot默认暴露health的endpoint,采用spring-boot的工程都可以利用这一点

为了能正确的检测到服务端的状态,可以考虑采用自定义的健康检查,因为通常健康检查都采用判断服务的进程以及端口是否存活,这种判断是粗糙的;例如Client强依赖后端的数据库,如果数据库宕机,Client对应的服务都无效,此时服务端如果进程和端口存活但数据库挂了,健康检查还判断服务存活显然是不合理

服务保护

服务熔断和降级

  • 熔断 不应信任其所有的依赖服务,采用线程池或信号量来实现服务的熔断 hystrix典型,也可以参考我实现的一个熔断小组件

   https://github.com/liaokailin/circuit-breaker

  • 降级 服务层面,存留核心服务,降级非核心服务 ;方法层面,实现降级方法,在服务不可用或被熔断后进入降级方法; 业务层面,存留核心业务

服务过载保护

  • 动态权限

  • 限流 令牌桶、漏桶、计数 令牌桶可以允许小型的波峰,漏桶是固定的流速,计数比较简单,可以参考我实现的一个限流小组组件

    https://github.com/liaokailin/rate-limiter

  • 节流

Cache


  • redis与memcached的区别

redis
    string list hash set sorted set
    分布式锁 setnx
memcached 
   string
   slat_class slat chunk
  • 分布式

redis集群+master/slave,采用16384slot,通过Client去定位slot; memcached靠一致性hash算法 

  • 缓存一致性

消息队列

  • Kafka与Rabbitmq

异步解耦的神器

  • kafka 具有高的吞吐量,consumer根据消费的offset,从broker上批量pull数据;无消息确认机制

topic -> partition->segement

  • RabbitMQ在吞吐量方面稍逊于kafka,他们的出发点不一样,rabbitMQ支持对消息的可靠的传递,支持事务,不支持批量的操作

 vhost exchange binding queue

     fanout 广播

     direct 按照routing key匹配

     topic 模糊匹配

     header

  • 分布式

Rabbitmq 镜像队列,主queue失效,miror queue接管 kafka的broker支持主备模式,采用zookeeper对集群中的broker、consumer进行管理


Database

  • 高可用

    MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案

  • 多主备+vip

  • 复制策略

半同步复制,全同步复制,异步复制

  • 读写分离 主写从读,冷热隔离,分表策略

读写一致性,不一致是因为写完成后,主从同步存在时间差,解决方案: 

  1. 半同步复制 ,原生功能,简单;写请求时延会增长,吞吐量会降低

  2. 读主库,不建议的操作,如果非要用需尽量减少读操作,例如cache 

  3. 缓存写key 

  4. 中间件


监控

  • 日志分析 elk接入

  • metrics prometheus

  • 应用监控 cat health endpoint 分布式定时任务调度(重试,幂等)

  • 链路监控 zipkin

  • 服务器监控 zabbix


无损发布

保证节点无流量后进行发版升级

分布式一致性


这属于额外的话题 cap理论,反acid模型的base理论,

两阶段提交协议(2PC),基于微服务的应用一般都使用SQL和NoSQL结合的模式,这些非关系型数据大多数并不支持2PC,分布式大部分追求最终一致性

实现最终一致性:

  • 可靠事件模式

  • 业务补偿模式

  • TCC模式

  • 对账



转载请注明
http://blog.csdn.net/liaokailin/article/details/66049607


欢迎关注,您的肯定是对我最大的支持


 

 


猜你喜欢

转载自blog.csdn.net/liaokailin/article/details/66049607