您的位置:首页 > 运维架构 > 网站架构

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

2017-03-25 23:18 239 查看
在公司做了一次高可用的分享,由于keynote的内容为大纲,特此加点注释说明,分享给大家,水平有限,欢迎拍砖~~分布式服务要素        分布式服务主要考虑如下几点:性能主要考虑指标: 响应时间,并发数,吞吐量常用的手段压缩,对传输数据进行压缩(类似合并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 & ServicesGateway也可以理解为一个微服务,因此统一讨论负载均衡实现软负载均衡,核心有三点:服务发现,发现依赖服务的列表服务选择规则,在多个服务中如何选择一个有效服务服务检测,检测失效的服务,高效剔除失效服务ribbon为典型的案例

服务发现与注册

consul,zk,dubboconsul是一个集服务发现与注册、配置、健康检查、多数据中心的工具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   分布式锁 setnxmemcached  string  slat_class slat chunk
分布式redis集群+master/slave,采用16384slot,通过Client去定位slot; memcached靠一致性hash算法 缓存一致性

消息队列

Kafka与Rabbitmq异步解耦的神器kafka 具有高的吞吐量,consumer根据消费的offset,从broker上批量pull数据;无消息确认机制topic -> partition->segementRabbitMQ在吞吐量方面稍逊于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复制策略半同步复制,全同步复制,异步复制读写分离 主写从读,冷热隔离,分表策略读写一致性,不一致是因为写完成后,主从同步存在时间差,解决方案: 半同步复制 ,原生功能,简单;写请求时延会增长,吞吐量会降低读主库,不建议的操作,如果非要用需尽量减少读操作,例如cache 缓存写key 中间件

监控

日志分析 elk接入metrics prometheus应用监控 cat health endpoint 分布式定时任务调度(重试,幂等)链路监控 zipkin服务器监控 zabbix

无损发布

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

分布式一致性

这属于额外的话题 cap理论,反acid模型的base理论,两阶段提交协议(2PC),基于微服务的应用一般都使用SQL和NoSQL结合的模式,这些非关系型数据大多数并不支持2PC,分布式大部分追求最终一致性实现最终一致性:可靠事件模式业务补偿模式TCC模式对账转载请注明 http://blog.csdn.net/liaokailin/article/details/66049607

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

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息