最近由于在实习期间接触到了京东的自研服务框架JSF,目前我写的一些新功能里面调用的下游接口就是JSF提供的。现有有很多高效的服务框架,如阿里巴巴的Dubbo配合Apache的ZooKeeper,那么为什么京东却自研了JSF服务框架呢?于是看了看京东的JSF的演化历史,不得不感叹好的架构果然不是一朝一夕就能实现的,都是逐步演变而来的。
Dubbo是阿里巴巴开源的一个高性能的服务框架,Dubbo使得应用之间可通过高性能的RPC实现服务的输出和输入功能,而且可以和 Spring框架无缝集成。我们可以看看Dubbo架构路线图:从单一应用架构 → 垂直应用架构 → 分布式服务架构 → 流动计算架构 ,也可以看我的另一篇文章《服务拆分方法论》:
从上图可以看出互联网的架构演变经历了单一应用架构、垂直应用架构、分布式服务架构和流动计算架构。服务的粒度越来越细化,多个Tomcat的Servlet之间相互调用,服务治理的尤为重要,所以一个优秀的架构来替我们解决服务之间的调用问题,而且还要保证高可用,甚至是实现负载均衡。于是Dubbo框架就出现了,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册与发现。
下面是Dubbo框架的架构图:
节点 | 说明 |
---|---|
Provider | 暴露服务的服务提供方 |
Consumer | 调用远程服务的服务消费方 |
Registry | 服务注册与发现的注册中心 |
Monitor | 统计服务的调用次数和调用时间的监控中心 |
Container | 服务运行容器 |
先用容器Container,通过Docker来启动我们的服务Provider。Dubbo本身没有使用任何的注册中心,而是用一种直连的方式进行的。但是,实际上很多时候都是使用 Dubbo + Zookeeper 的方式,使用 zookeeper 作为注册中心,服务调用方Comsumer就会去注册中心去订阅Subscribe相关服务。注册中心会异步的方式将消费者需要的服务的地址列表推送Notify给你。消费者就会将整个地址列表缓存在本地,当业务需求到来时,就会使用地址列表里的地址去请求相关的服务程序。至于Monitor顾名思义就是监视器的含义,消费者和提供者会定时将服务的调用次数和被调用的次数发送给监视器。关于Dubbo和Zookeeper的使用案例在此就不介绍了,可以参考《Dubbo一篇文章就够了:从入门到实战》。
当我们提出“Zookeeper作为注册中心合适吗”这个问题的时候,首先考虑的是具体使用场景,我想说的是,在京东,Zookeeper真的不合适!
关于服务注册中心重要性不必多说,注册中心相当于是服务提供者和服务调用者之间的引路人,在服务治理中的作用极为重要,注册中心必须必须必须是高可用的,拥有极强的稳定性。那么如何选择服务器注册中心呢?下面列出一些作为注册中心基本要考量点:
状态检测尤其重要,因为这个要是检测不准确会误判,导致严重后果,例如Zookeeper是强一致性的,Zookeeper根据服务端注册的临时节点进行状态检测,如果服务端和Zookeeper之间的网络闪断,导致Zookeeper认为服务端已经死了,从而摘掉这个节点;但是其实客户端和服务端直接的网络是好的,这样就有可能把节点全部摘掉,导致无可用节点。
如果是从开源框架里面选择,那么还需要考量:
下面比较一下我知道的两个注册中心
ZooKeeper | Eureka | |
---|---|---|
一致性 | 强一致性 | 弱一致性 |
数据结构 | Tree | K/V |
通讯协议 | TCP | HTTP |
客户端 | ZKClient | Eureka-client |
CAP原则 | CP | AP |
注册中心的选型总结:
说完了注册中心选型和特点后,我们再来分析Zookeeper是否在适合在京东作为服务注册中心,答案是不适合。Zookeeper在大流量场景下不适合作为注册中心,因为Zookeeper不是为高可用性设计的。
由于要跨机房容灾,很多系统实际上是需要跨机房部署的。出于性价比的考虑我们通常会让多个机房同时工作,而不会搭建N倍的冗余。也就是说单个机房肯定撑不住全流量。由于Zookeeper集群只能有一个master节点,因此一旦机房之间连接出现故障,Zookeeper master就只能照顾一个机房,其他机房运行的业务模块由于没有master都只能停掉。于是所有流量集中到有master的那个机房,于是系统宕机。 这是就是京东在2015年的双十一注册中心挂掉的根本原因。后端容器服务重启以后之前缓存的服务地址列表丢失,服务无法调用。而且Zookeeper没有动态水平扩展的能力,Zookeeper作为注册中心称为了双十一这种高并发场景下的瓶颈。
即使是在同一个机房里面,由于网段的不同,在调整机房交换机的时候偶尔也会发生网段隔离的情况。实际上机房每个月基本上都会发生短暂的网络隔离之类的子网段调整。在那个时刻Zookeeper将处于不可用状态。如果整个业务系统基于Zookeeper(比如要求每个业务请求都先去Zookeeper获取业务系统的master地址),则系统的可用性将非常脆弱。由于Zookeeper对于网络隔离的极度敏感,导致Zookeeper对于网络的任何风吹草动都会做出激烈反应。这使得Zookeeper的服务失效时间比较多,Zookeeper的不可用将导致整个系统的不可用。
提供一个接口文档管理以及接口查询的入口,可以是一个公共的WIKI,也可以是独立的系统,等等。这里可以定义接口的文档,包括接口描述,方法定义,字段定义。可以定义接口的SLA,包括支持的并发数,建议配置是什么。还有就是接口的负责人等一些查询的入口。
提供一个配置管理的地方,这里说的配置主要指的是服务相关的一些配置。配置包括分组配置、路由策略、黑白名单、降级开关、限流信息、超时时间、重试次数等等,任何可以动态变更的所有数据。这样服务提供者和服务调用者可以不需要重启自己的应用,直接进行配置的变更。配置中心可以独立于注册中心,也可以和注册中心合并。
监控服务关注接口维度,实例(例如所在JVM实例)维度的数据。RPC框架可以定时上报调用次数,耗时,异常等信息。监控中心可以统计出服务质量信息,也可以进行监控报警。
区别于监控中心,以调用链的模式对服务进行。RPC框架作为分布式跟踪系统的一个天然埋点,可以很好的进行一个数据输出。
我这边列了常见的服务治理功能,例如:
RPC框架大部分场景都是自己调用的,什么时候会需要一个网关呢?
网关可以提供如下功能:
JSF早期叫做SAF,当时的选择如下:
目前的JSF几乎是全部自研
目前的JSF是基于DB做的数据最终一致,也就是AP系统。注册中心主要实现的就是服务列表的注册订阅推送,服务配置的获取下发,服务状态的实时查看等功能。注册中心节点是无状态的,可水平扩展的。整个注册中心集群下的所有注册中心几点都是等价的。
本文作者:Tim
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!