目标:介绍接下来集群分哪几部分来描述,介绍dubbo在集群中涉及到的几个功能,介绍dubbo-cluster下跟各个功能相关的接口
如果说分布式是爸爸住在杭州,妈妈住在上海,那么集群就是两个爸爸,一个住在杭州,一个住在上海。对于分布式和集群有高吞吐量、高可用的目标。对于分布式来说每个服务器部署的服务任务是不同的,可能需要这些服务器上的服务共同协作才能完成整个业务流程,各个服务各司其职。而集群不一样,集群是同一个服务,被部署在了多个服务器上,每个服务器的任务都是一样的,是为了减少压力集中的问题,而集群中就会出现负载均衡、容错等问题。
dubbo的集群涉及到以下几部分内容:
以上几部分跟 《dubbo源码解析(一)Hello,Dubbo》 的"(二)dubbo-cluster——集群模块“介绍有些类似,这里再重新讲一遍是为了明确我接下来介绍集群模块的文章内容分布,也就是除了本文之外,我会用七篇文章来讲解以上的七部分,不管内容多少,只是为了把相应内容区分开来,能让读者有选择性的阅读。
在官方网站上有一段介绍我觉得写的非常的好:
集群工作过程可分为两个阶段,第一个阶段是在服务消费者初始化期间,集群 Cluster 实现类为服务消费者创建 Cluster Invoker 实例,即上图中的 merge 操作。第二个阶段是在服务消费者进行远程调用时。以 FailoverClusterInvoker 为例,该类型 Cluster Invoker 首先会调用 Directory 的 list 方法列举 Invoker 列表(可将 Invoker 简单理解为服务提供者)。Directory 的用途是保存 Invoker,可简单类比为 List<invoker>。其实现类 RegistryDirectory 是一个动态服务目录,可感知注册中心配置的变化,它所持有的 Inovker 列表会随着注册中心内容的变化而变化。每次变化后,RegistryDirectory 会动态增删 Inovker,并调用 Router 的 route 方法进行路由,过滤掉不符合路由规则的 Invoker。当 FailoverClusterInvoker 拿到 Directory 返回的 Invoker 列表后,它会通过 LoadBalance 从 Invoker 列表中选择一个 Inovker。最后 FailoverClusterInvoker 会将参数传给 LoadBalance 选择出的 Invoker 实例的 invoker 方法,进行真正的远程调用。
本文要来讲的无非就是这几部分内容的一个大概,并且介绍一下这几部分内容涉及到的接口。集群的包结构我就不在这里展示了,就是 《dubbo源码解析(一)Hello,Dubbo》 的"(二)dubbo-cluster——集群模块“中的图片。下面我们直接对应各个部分来介绍相应的接口源码。
关于目录介绍请查看 《dubbo源码解析(一)Hello,Dubbo》 的"(二)dubbo-cluster——集群模块“介绍。
@SPI(FailoverCluster.NAME) public interface Cluster { /** * Merge the directory invokers to a virtual invoker. * 将目录调用程序合并到虚拟调用程序。 * @param <T> * @param directory * @return cluster invoker * @throws RpcException */ @Adaptive <T> Invoker<T> join(Directory<T> directory) throws RpcException; } 复制代码
该接口是集群容错接口,可以看到它是一个可扩展接口,默认实现FailoverCluster,当然它还会有其他的实现,每一种实现都代表了一种集群容错的方式,具体有哪些,可以看下面文章的介绍,他们都在support包下面,在本文只是让读者知道接口的定义。那么它还定义了一个join方法,作用就是把Directory对象变成一个 Invoker 对象用来后续的一系列调用。该Invoker代表了一个集群实现。似懂非懂就够了,后面看具体的实现会比较清晰。
public interface Configurator extends Comparable<Configurator> { /** * get the configurator url. * 配置规则,生成url * @return configurator url. */ URL getUrl(); /** * Configure the provider url. * 把规则配置到URL中 * * @param url - old rovider url. * @return new provider url. */ URL configure(URL url); } 复制代码
该接口是配置规则的接口,定义了两个方法,第一个是配置规则,并且生成url,第二个是把配置配置到旧的url中,其实都是在url上应用规则。
@SPI public interface ConfiguratorFactory { /** * get the configurator instance. * 获得configurator实例 * @param url - configurator url. * @return configurator instance. */ @Adaptive("protocol") Configurator getConfigurator(URL url); } 复制代码
该接口是Configurator的工厂接口,定义了一个getConfigurator方法来获得Configurator实例,比较好理解。
public interface Directory<T> extends Node { /** * get service type. * 获得服务类型 * @return service type. */ Class<T> getInterface(); /** * list invokers. * 获得所有服务Invoker集合 * @return invokers */ List<Invoker<T>> list(Invocation invocation) throws RpcException; } 复制代码
该接口是目录接口,Directory 代表了多个 Invoker,并且它的值会随着注册中心的服务变更推送而变化 。一个服务类型对应一个Directory。定义的两个方法也比较好理解。
@SPI(RandomLoadBalance.NAME) public interface LoadBalance { /** * select one invoker in list. * 选择一个合适的调用,并且返回 * @param invokers invokers. * @param url refer url * @param invocation invocation. * @return selected invoker. */ @Adaptive("loadbalance") <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException; } 复制代码
该接口是负载均衡的接口,dubbo也提供了四种负载均衡策略,也会在下面文章讲解。
@SPI public interface Merger<T> { /** * 合并T数组,返回合并后的T对象 * @param items * @return */ T merge(T... items); } 复制代码
该接口是分组聚合,将某对象数组合并为一个对象。
public interface Router extends Comparable<Router> { /** * get the router url. * 获得路由规则的url * @return url */ URL getUrl(); /** * route. * 筛选出跟规则匹配的Invoker集合 * @param invokers * @param url refer url * @param invocation * @return routed invokers * @throws RpcException */ <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException; } 复制代码
该接口是路由规则的接口,定义的两个方法,第一个方法是获得路由规则的url,第二个方法是筛选出跟规则匹配的Invoker集合。
@SPI public interface RouterFactory { /** * Create router. * 创建路由 * @param url * @return router */ @Adaptive("protocol") Router getRouter(URL url); } 复制代码
该接口是路由工厂接口,定义了获得路由实例的方法。