⑴ bbo实际应用是需要配置消费者吗
1. Dubbo是什么?Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。简单的说,bbo就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有bbo这样的分布式服务框架的需求,并且本质上是个服务调用的东东,说白了就是个远程服务调用的分布式框架(告别Web Service模式中的WSdl,以服务者与消费者的方式在bbo上注册)其核心部分包含:1. 远程通讯: 提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。2. 集群容错: 提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。3. 自动发现: 基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。2. Dubbo能做什么?1.透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。 2.软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。3. 服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。Dubbo采用全Spring配置方式,透明化接入应用,对应用没有任何API侵入,只需用Spring加载Dubbo的配置即可,Dubbo基于Spring的Schema扩展进行加载。之前使用Web Service,我想测试接口可以通过模拟消息的方式通过soapui或LR进行功能测试或性能测试。但现在使用Dubbo,接口之间不能直接交互,我尝试通过模拟消费者地址测试,结果不堪入目,再而使用jmeter通过junit进行测试,但还是需要往bbo上去注册,如果再不给提供源代码的前提下,这个测试用例不好写啊….3. bbo的架构bbo架构图如下所示:节点角色说明:Provider: 暴露服务的服务提供方。Consumer: 调用远程服务的服务消费方。Registry: 服务注册与发现的注册中心。Monitor: 统计服务的调用次调和调用时间的监控中心。Container: 服务运行容器。这点我觉得非常好,角色分明,可以根据每个节点角色的状态来确定该服务是否正常。调用关系说明:0 服务容器负责启动,加载,运行服务提供者。1. 服务提供者在启动时,向注册中心注册自己提供的服务。2. 服务消费者在启动时,向注册中心订阅自己所需的服务。3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。bbo的容错性显而易见,性能方面还没有还得及测,我们系统某页面需要掉5次接口,本来想建议做个缓存,但业务关系不能采纳,还需要研究下bbo的性能调优问题…4. bbo使用方法。Dubbo采用全Spring配置方式,透明化接入应用,对应用没有任何API侵入,只需用Spring加载Dubbo的配置即可,Dubbo基于Spring的Schema扩展进行加载。如果不想使用Spring配置,而希望通过API的方式进行调用(不推荐)下面我们就来看看spring配置方式的写法:服务提供者:1. 下载zookeeper注册中心,下载地址: 下载后解压即可,进入D:apach-zookeeper-3.4.5bin,双击zkServer.cmd启动注册中心服务。2. 定义服务接口: (该接口需单独打包,在服务提供方和消费方共享)下面这个例子不错,写的很详细可以做个model.package com.unj.bbotest.provider; import java.util.List; public interface DemoService { String sayHello(String name); public List getUsers(); } 在服务提供方实现接口:(对服务消费方隐藏实现)package com.unj.bbotest.provider; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; public class DemoServiceImpl implements DemoService{ public String sayHello(String name) { return "Hello " + name; } public List getUsers() { List list = new ArrayList(); User u1 = new User(); u1.setName("jack"); u1.setAge(20); u1.setSex("男"); User u2 = new User(); u2.setName("tom"); u2.setAge(21); u2.setSex("女"); User u3 = new User(); u3.setName("rose"); u3.setAge(19); u3.setSex("女"); list.add(u1); list.add(u2); list.add(u3); return list; } } 用Spring配置声明暴露服务:<beans xmlns="" xmlns:xsi="" xmlns:bbo="" xsi:schemaLocation=" /spring-beans.xsd /bbo.xsd "> <!– 使用multicast广播注册中心暴露服务地址 –> 加载Spring配置,启动服务:package com.unj.bbotest.provider; import org.springframework.context.support.; public class Provider { public static void main(String[] args) throws Exception { context = new (new String[] {"applicationContext.xml"}); context.start(); System.in.read(); // 为保证服务一直开着,利用输入流的阻塞来模拟 } } 服务消费者:applicationContext-bbo.xml 中注册自己需要调用的接口,我刚开始测试的时候需要的接口很多,所以把这个文件写的满满的,后来熟悉了把接口按业务类型分开,写了N多个 applicationContext-bbo-***.xml 简练多了 》。 1.通过Spring配置引用远程服务: <beans xmlns="" xmlns:xsi="" xmlns:bbo="" xsi:schemaLocation=" /spring-beans.xsd /bbo.xsd "> <!– –> <bbo:reference id="demoService" interface="com.unj.bbotest.provider.DemoService" /> 2.加载Spring配置,并调用远程服务:package com.alibaba.bbo.demo.pp; import java.util.List; import org.springframework.context.support.; import com.unj.bbotest.provider.DemoService; public class Consumer { public static void main(String[] args) throws Exception { context = new ( new String[] { "applicationContext.xml" }); context.start(); DemoService demoService = (DemoService) context.getBean("demoService"); // String hello = demoService.sayHello("tom"); // ? System.out.println(hello); // // List list = demoService.getUsers(); if (list != null && list.size() > 0) { for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } } // System.out.println(demoService.hehe()); System.in.read(); } }/
⑵ 如何清除bbo lur缓存
Dubbo缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止专Spring初始化完成,以便上属线时,能及早发现问题,默认check=true。如果你的Spring容器是懒加载的,或者通过API编程延迟引用服务,请关闭check,否则服务临时不可用时,会抛出异常,拿到null引用,如果check=false,总是会返回引用,当服务恢复时,能自动连上。
⑶ 如何更好地学习bbo源代码
一、Dubbo整体架构1、Dubbo与Spring的整合Dubbo在使用上可以做到非常简单,不管是Provider还是Consumer都可以通过Spring的配置文件进行配置,配置完之后,就可以像使用spring bean一样进行服务暴露和调用了,完全看不到bbo api的存在。这是因为bbo使用了spring提供的可扩展Schema自定义配置支持。在spring配置文件中,可以像、这样进行配置。META-INF下的spring.handlers文件中指定了bbo的xml解析类:DubboNamespaceHandler。像前面的被解析成ServiceConfig,被解析成ReferenceConfig等等。 2、jdk spi扩展由于Dubbo是开源框架,必须要提供很多的可扩展点。Dubbo是通过扩展jdk spi机制来实现可扩展的。具体来说,就是在META-INF目录下,放置文件名为接口全称,文件中为key、value键值对,value为具体实现类的全类名,key为标志值。由于bbo使用了url总线的设计,即很多参数通过URL对象来传递,在实际中,具体要用到哪个值,可以通过url中的参数值来指定。 Dubbo对spi的扩展是通过ExtensionLoader来实现的,查看ExtensionLoader的源码,可以看到Dubbo对jdk spi做了三个方面的扩展: (1)jdk spi仅仅通过接口类名获取所有实现,而ExtensionLoader则通过接口类名和key值获取一个实现; (2)Adaptive实现,就是生成一个代理类,这样就可以根据实际调用时的一些参数动态决定要调用的类了。 (3)自动包装实现,这种实现的类一般是自动激活的,常用于包装类,比如Protocol的两个实现类:ProtocolFilterWrapper、ProtocolListenerWrapper。 3、url总线设计Dubbo为了使得各层解耦,采用了url总线的设计。我们通常的设计会把层与层之间的交互参数做成Model,这样层与层之间沟通成本比较大,扩展起来也比较麻烦。因此,Dubbo把各层之间的通信都采用url的形式。比如,注册中心启动时,参数的url为: registry://0.0.0.0:9090?codec=registry&transporter=netty 这就表示当前是注册中心,绑定到所有ip,端口是9090,解析器类型是registry,使用的底层网络通信框架是netty。 二、Dubbo启动过程Dubbo分为注册中心、服务提供者(provider)、服务消费者(consumer)三个部分。 1、注册中心启动过程注册中心的启动过程,主要看两个类:RegistrySynchronizer、RegistryReceiver,两个类的初始化方法都是start。 RegistrySynchronizer的start方法: (1)把所有配置信息load到内存; (2)把当前注册中心信息保存到数据库; (3)启动5个定时器。 5个定时器的功能是: (1)AutoRedirectTask,自动重定向定时器。默认1小时运行1次。如果当前注册中心的连接数高于平均值的1.2倍,则将多出来的连接数重定向到其他注册中心上,以达到注册中心集群的连接数均衡。 (2)DirtyCheckTask,脏数据检查定时器。作用是:分别检查缓存provider、数据库provider、缓存consumer、数据库consumer的数据,清除脏数据;清理不存活的provider和consumer数据;对于缓存中的存在的provider或consumer而数据库不存在,重新注册和订阅。 (3)ChangedClearTask,changes变更表的定时清理任务。作用是读取changes表,清除过期数据。 (4)AlivedCheckTask,注册中心存活状态定时检查,会定时更新registries表的expire字段,用以判断注册中心的存活状态。如果有新的注册中心,发送同步消息,将当前所有注册中心的地址通知到所有客户端。 (5)ChangedCheckTask,变更检查定时器。检查changes表的变更,检查类型包括:参数覆盖变更、路由变更、服务消费者变更、权重变更、负载均衡变更。 RegistryReceiver的start方法:启动注册中心服务。默认使用netty框架,绑定本机的9090端口。最后启动服务的过程是在NettyServer来完成的。接收消息时,抛开bbo协议的解码器,调用类的顺序是 NettyHandler-》NettyServer-》MultiMessageHandler-》HeartbeatHandler-》AllDispatcher-》DecodeHandler-》HeaderExchangeHandler-》RegistryReceiver-》RegistryValidator-》RegistryFailover-》RegistryExecutor。2、provider启动过程provider的启动过程是从ServiceConfig的export方法开始进行的,具体步骤是: (1)进行本地jvm的暴露,不开放任何端口,以提供injvm这种形式的调用,这种调用只是本地调用,不涉及进程间通信。 (2)调用RegistryProtocol的export。 (3)调用DubboProtocol的export,默认开启20880端口,用以提供接收consumer的远程调用服务。 (4)通过新建RemoteRegistry来建立与注册中心的连接。 (5)将服务地址注册到注册中心。 (6)去注册中心订阅自己的服务。 3、consumer启动过程consumer的启动过程是通过ReferenceConfig的get方法进行的,具体步骤是: (1)通过新建RemoteRegistry来建立与注册中心的连接。 (2)新建RegistryDirectory并向注册中心订阅服务,RegistryDirectory用以维护注册中心获取的服务相关信息。 (3)创建代理类,发起consumer远程调用时,实际调用的是InvokerInvocationHandler。 三、实际调用过程consumer端发起调用时,实际调用经过的类是: 1、consumer: InvokerInvocationHandler-》MockClusterInvoker(如果配置了Mock,则直接调用本地Mock类)-》FailoverClusterInvoker(负载均衡,容错机制,默认在发生错误的情况下,进行两次重试)-》RegistryDirectory$InvokerDelegete-》ConsumerContextFilter-》FutureFilter->DubboInvoker NettyServer-》MultiMessageHandler-》HeartbeatHandler-》AllDispatcher-》DecodeHandler-》HeaderExchangeHandler-》DubboProtocol.requestHandler-》EchoFilter-》ClassLoaderFilter-》GenericFilter-》ContextFilter-》ExceptionFilter-》TimeoutFilter-》MonitorFilter-》TraceFilter-》实际service。四、Dubbo使用的设计模式1、工厂模式ServiceConfig中有个字段,代码是这样的: private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();Dubbo里有很多这种代码。这也是一种工厂模式,只是实现类的获取采用了jdk spi的机制。这么实现的优点是可扩展性强,想要扩展实现,只需要在classpath下增加个文件就可以了,代码零侵入。另外,像上面的Adaptive实现,可以做到调用时动态决定调用哪个实现,但是由于这种实现采用了动态代理,会造成代码调试比较麻烦,需要分析出实际调用的实现类。 2、装饰器模式Dubbo在启动和调用阶段都大量使用了装饰器模式。以Provider提供的调用链为例,具体的调用链代码是在ProtocolFilterWrapper的buildInvokerChain完成的,具体是将注解中含有group=provider的Filter实现,按照order排序,最后的调用顺序是 EchoFilter-》ClassLoaderFilter-》GenericFilter-》ContextFilter-》ExceptionFilter-》TimeoutFilter-》MonitorFilter-》TraceFilter。更确切地说,这里是装饰器和责任链模式的混合使用。例如,EchoFilter的作用是判断是否是回声测试请求,是的话直接返回内容,这是一种责任链的体现。而像ClassLoaderFilter则只是在主功能上添加了功能,更改当前线程的ClassLoader,这是典型的装饰器模式。 3、观察者模式Dubbo的provider启动时,需要与注册中心交互,先注册自己的服务,再订阅自己的服务,订阅时,采用了观察者模式,开启一个listener。注册中心会每5秒定时检查是否有服务更新,如果有更新,向该服务的提供者发送一个notify消息,provider接受到notify消息后,即运行NotifyListener的notify方法,执行监听器方法。 4、动态代理模式Dubbo扩展jdk spi的类ExtensionLoader的Adaptive实现是典型的动态代理实现。Dubbo需要灵活地控制实现类,即在调用阶段动态地根据参数决定调用哪个实现类,所以采用先生成代理类的方法,能够做到灵活的调用。生成代理类的代码是ExtensionLoader的方法。代理类的主要逻辑是,获取URL参数中指定参数的值作为获取实现类的key。
⑷ Dubbo——路由机制(下)
在 Dubbo——路由机制(上) ,介绍了 Router 接口的基本功能以及 RouterChain 加载多个 Router 的实现,之后介绍了 ConditionRouter 这个类对条件路由规则的处理逻辑以及 ScriptRouter 这个类对脚本路由规则的处理逻辑。本文继续介绍剩余的三个 Router 接口实现类。 FileRouterFactory 是 ScriptRouterFactory 的装饰器,其扩展名为 file,FileRouterFactory 在 ScriptRouterFactory 基础上增加了读取文件的能力。可以将 ScriptRouter 使用的路由规则保存到文件中,然后在 URL 中指定文件路径,FileRouterFactory 从中解析到该脚本文件的路径并进行读取,调用 ScriptRouterFactory 去创建相应的 ScriptRouter 对象。 下面来看 FileRouterFactory 对 getRouter() 方法的具体实现,其中完成了 file 协议的 URL 到 script 协议 URL 的转换,如下是一个转换示例,首先会将 file:// 协议转换成 script:// 协议,然后会添加 type 参数和 rule 参数,其中 type 参数值根据文件后缀名确定,该示例为 js,rule 参数值为文件内容。 可以再结合接下来这个示例分析 getRouter() 方法的具体实现: TagRouterFactory 作为 RouterFactory 接口的扩展实现,其扩展名为 tag。但是需要注意的是,TagRouterFactory 与之前介绍的 ConditionRouterFactory、ScriptRouterFactory 的不同之处在于,它是通过继承 CacheableRouterFactory 这个抽象类,间接实现了 RouterFactory 接口。 CacheableRouterFactory 抽象类中维护了一个 ConcurrentMap 集合(routerMap 字段)用来缓存 Router,其中的 Key 是 ServiceKey。在 CacheableRouterFactory 的 getRouter() 方法中,会优先根据 URL 的 ServiceKey 查询 routerMap 集合,查询失败之后会调用 createRouter() 抽象方法来创建相应的 Router 对象。在 TagRouterFactory.createRouter() 方法中,创建的自然就是 TagRouter 对象了。 通过 TagRouter,可以将某一个或多个 Provider 划分到同一分组,约束流量只在指定分组中流转,这样就可以轻松达到流量隔离的目的,从而支持灰度发布等场景。 目前,Dubbo 提供了动态和静态两种方式给 Provider 打标签,其中动态方式就是通过服务治理平台动态下发标签,静态方式就是在 XML 等静态配置中打标签。Consumer 端可以在 RpcContext 的 attachment 中添加 request.tag 附加属性,注意保存在 attachment 中的值将会在一次完整的远程调用中持续传递,我们只需要在起始调用时进行设置,就可以达到标签的持续传递。 了解了 Tag 的基本概念和功能之后,再简单介绍一个 Tag 的使用示例。 在实际的开发测试中,一个完整的请求会涉及非常多的 Provider,分属不同团队进行维护,这些团队每天都会处理不同的需求,并在其负责的 Provider 服务中进行修改,如果所有团队都使用一套测试环境,那么测试环境就会变得很不稳定。如下图所示,4 个 Provider 分属不同的团队管理,Provider 2 和 Provider 4 在测试环境测试,部署了有 Bug 的版本,这样就会导致整个测试环境无法正常处理请求,在这样一个不稳定的测试环境中排查 Bug 是非常困难的,因为可能排查到最后,发现是别人的 Bug。 为了解决上述问题,我们可以针对每个需求分别独立出一套测试环境,但是这个方案会占用大量机器,前期的搭建成本以及后续的维护成本也都非常高。 下面是一个通过 Tag 方式实现环境隔离的架构图,其中,需求 1 对 Provider 2 的请求会全部落到有需求 1 标签的 Provider 上,其他 Provider 使用稳定测试环境中的 Provider;需求 2 对 Provider 4 的请求会全部落到有需求 2 标签的 Provider 4 上,其他 Provider 使用稳定测试环境中的 Provider。 在一些特殊场景中,会有 Tag 降级的场景,比如找不到对应 Tag 的 Provider,会按照一定的规则进行降级。如果在 Provider 集群中不存在与请求 Tag 对应的 Provider 节点,则默认将降级请求 Tag 为空的 Provider;如果希望在找不到匹配 Tag 的 Provider 节点时抛出异常的话,我们需设置 request.tag.force = true。 如果请求中的 request.tag 未设置,只会匹配 Tag 为空的 Provider,也就是说即使集群中存在可用的服务,若 Tag 不匹配也就无法调用。一句话总结,携带 Tag 的请求可以降级访问到无 Tag 的 Provider,但不携带 Tag 的请求永远无法访问到带有 Tag 的 Provider。 下面再来看 TagRouter 的具体实现。在 TagRouter 中持有一个 TagRouterRule 对象的引用,在 TagRouterRule 中维护了一个 Tag 集合,而在每个 Tag 对象中又都维护了一个 Tag 的名称,以及 Tag 绑定的网络地址集合,如下图所示: 另外,在 TagRouterRule 中还维护了 addressToTagnames、tagnameToAddresses 两个集合(都是 Map<String, List<String>> 类型),分别记录了 Tag 名称到各个 address 的映射以及 address 到 Tag 名称的映射。在 TagRouterRule 的 init() 方法中,会根据 tags 集合初始化这两个集合。 了解了 TagRouterRule 的基本构造之后,我们继续来看 TagRouter 构造 TagRouterRule 的过程。TagRouter 除了实现了 Router 接口之外,还实现了 ConfigurationListener 接口,如下图所示: ConfigurationListener 用于监听配置的变化,其中就包括 TagRouterRule 配置的变更。当我们通过动态更新 TagRouterRule 配置的时候,就会触发 ConfigurationListener 接口的 process() 方法,TagRouter 对 process() 方法的实现如下: 我们可以看到,如果是删除配置的操作,则直接将 tagRouterRule 设置为 null,如果是修改或新增配置,则通过 TagRuleParser 解析传入的配置,得到对应的 TagRouterRule 对象。TagRuleParser 可以解析 yaml 格式的 TagRouterRule 配置,下面是一个配置示例: 经过 TagRuleParser 解析得到的 TagRouterRule 结构,如下所示: 除了上图展示的几个集合字段,TagRouterRule 还从 AbstractRouterRule 抽象类继承了一些控制字段,后面介绍的 ConditionRouterRule 也继承了 AbstractRouterRule。 AbstractRouterRule 中核心字段的具体含义大致可总结为如下: 我们可以看到,AbstractRouterRule 中的核心字段与前面的示例配置是一一对应的。 我们知道,Router 最终目的是要过滤符合条件的 Invoker 对象,下面我们一起来看 TagRouter 是如何使用 TagRouterRule 路由逻辑进行 Invoker 过滤的,大致步骤如下: 上述流程的具体实现是在 TagRouter.route() 方法中,如下所示: 除了之前介绍的 TagRouterFactory 继承了 CacheableRouterFactory 之外,ServiceRouterFactory 也继承 CachabelRouterFactory,具有了缓存的能力,具体继承关系如下图所示: ServiceRouterFactory 创建的 Router 实现是 ServiceRouter,与 ServiceRouter 类似的是 AppRouter,两者都继承了 ListenableRouter 抽象类(虽然 ListenableRouter 是个抽象类,但是没有抽象方法留给子类实现),继承关系如下图所示: ListenableRouter 在 ConditionRouter 基础上添加了动态配置的能力,ListenableRouter 的 process() 方法与 TagRouter 中的 process() 方法类似,对于 ConfigChangedEvent.DELETE 事件,直接清空 ListenableRouter 中维护的 ConditionRouterRule 和 ConditionRouter 集合的引用;对于 ADDED、UPDATED 事件,则通过 ConditionRuleParser 解析事件内容,得到相应的 ConditionRouterRule 对象和 ConditionRouter 集合。这里的 ConditionRuleParser 同样是以 yaml 文件的格式解析 ConditionRouterRule 的相关配置。ConditionRouterRule 中维护了一个 conditions 集合(List<String> 类型),记录了多个 Condition 路由规则,对应生成多个 ConditionRouter 对象。 整个解析 ConditionRouterRule 的过程,与前文介绍的解析 TagRouterRule 的流程类似。 在 ListenableRouter 的 route() 方法中,会遍历全部 ConditionRouter 过滤出符合全部路由条件的 Invoker 集合,具体实现如下: ServiceRouter 和 AppRouter 都是简单地继承了 ListenableRouter 抽象类,且没有覆盖 ListenableRouter 的任何方法,两者只有以下两点区别。 本文我们是紧接 Dubbo——路由机制(上) 的内容,继续介绍了剩余 Router 接口实现的内容。 我们介绍了基于文件的 FileRouter 实现,其底层会依赖之前介绍的 ScriptRouter;接下来又讲解了基于 Tag 的测试环境隔离方案,以及如何基于 TagRouter 实现该方案,同时深入分析了 TagRouter 的核心实现;最后我们还介绍了 ListenableRouter 抽象类以及 ServerRouter 和 AppRouter 两个实现,它们是在条件路由的基础上添加了动态变更路由规则的能力,同时区分了服务级别和服务实例级别的配置。
⑸ 关于bbo在linux环境weblogic下启动报错
现在一般能打开64个。 文件描述符的范围是0 ~ O P E N _ M A X 。早期的U N I X版本采用的上限值是1 9 (允许每个进程打开2 0个文件),现在很多系统则将其增加至6 3。
⑹ Dubbo——HTTP 协议 + JSON-RPC
Protocol 还有一个实现分支是 AbstractProxyProtocol,如下图所示: 从图中我们可以看到:gRPC、HTTP、WebService、Hessian、Thrift 等协议对应的 Protocol 实现,都是继承自 AbstractProxyProtocol 抽象类。 目前互联网的技术栈百花齐放,很多公司会使用 Node.js、Python、Rails、Go 等语言来开发 一些 Web 端应用,同时又有很多服务会使用 Java 技术栈实现,这就出现了大量的跨语言调用的需求。Dubbo 作为一个 RPC 框架,自然也希望能实现这种跨语言的调用,目前 Dubbo 中使用“HTTP 协议 + JSON-RPC”的方式来达到这一目的,其中 HTTP 协议和 JSON 都是天然跨语言的标准,在各种语言中都有成熟的类库。 下面就重点来分析 Dubbo 对 HTTP 协议的支持。首先,会介绍 JSON-RPC 的基础,并通过一个示例,快速入门,然后介绍 Dubbo 中 HttpProtocol 的具体实现,也就是如何将 HTTP 协议与 JSON-RPC 结合使用,实现跨语言调用的效果。 Dubbo 中支持的 HTTP 协议实际上使用的是 JSON-RPC 协议。 JSON-RPC 是基于 JSON 的跨语言远程调用协议。Dubbo 中的 bbo-rpc-xml、bbo-rpc-webservice 等模块支持的 XML-RPC、WebService 等协议与 JSON-RPC 一样,都是基于文本的协议,只不过 JSON 的格式比 XML、WebService 等格式更加简洁、紧凑。与 Dubbo 协议、Hessian 协议等二进制协议相比,JSON-RPC 更便于调试和实现,可见 JSON-RPC 协议还是一款非常优秀的远程调用协议。 在 Java 体系中,有很多成熟的 JSON-RPC 框架,例如 jsonrpc4j、jpoxy 等,其中,jsonrpc4j 本身体积小巧,使用方便,既可以独立使用,也可以与 Spring 无缝集合,非常适合基于 Spring 的项目。 下面先来看看 JSON-RPC 协议中请求的基本格式: JSON-RPC请求中各个字段的含义如下: 在 JSON-RPC 的服务端收到调用请求之后,会查找到相应的方法并进行调用,然后将方法的返回值整理成如下格式,返回给客户端: JSON-RPC响应中各个字段的含义如下: Dubbo 使用 jsonrpc4j 库来实现 JSON-RPC 协议,下面使用 jsonrpc4j 编写一个简单的 JSON-RPC 服务端示例程序和客户端示例程序,并通过这两个示例程序说明 jsonrpc4j 最基本的使用方式。 首先,需要创建服务端和客户端都需要的 domain 类以及服务接口。先来创建一个 User 类,作为最基础的数据对象: 接下来创建一个 UserService 接口作为服务接口,其中定义了 5 个方法,分别用来创建 User、查询 User 以及相关信息、删除 User: UserServiceImpl 是 UserService 接口的实现类,其中使用一个 ArrayList 集合管理 User 对象,具体实现如下: 整个用户管理业务的核心大致如此。下面我们来看服务端如何将 UserService 与 JSON-RPC 关联起来。 首先,创建 RpcServlet 类,它是 HttpServlet 的子类,并覆盖了 HttpServlet 的 service() 方法。我们知道,HttpServlet 在收到 GET 和 POST 请求的时候,最终会调用其 service() 方法进行处理;HttpServlet 还会将 HTTP 请求和响应封装成 HttpServletRequest 和 HttpServletResponse 传入 service() 方法之中。这里的 RpcServlet 实现之中会创建一个 JsonRpcServer,并在 service() 方法中将 HTTP 请求委托给 JsonRpcServer 进行处理: 最后,创建一个 JsonRpcServer 作为服务端的入口类,在其 main() 方法中会启动 Jetty 作为 Web 容器,具体实现如下: 这里使用到的 web.xml 配置文件如下: 完成服务端的编写之后,下面再继续编写 JSON-RPC 的客户端。在 JsonRpcClient 中会创建 JsonRpcHttpClient,并通过 JsonRpcHttpClient 请求服务端: 在 AbstractProxyProtocol 的 export() 方法中,首先会根据 URL 检查 exporterMap 缓存,如果查询失败,则会调用 ProxyFactory.getProxy() 方法将 Invoker 封装成业务接口的代理类,然后通过子类实现的 doExport() 方法启动底层的 ProxyProtocolServer,并初始化 serverMap 集合。具体实现如下: 在 HttpProtocol 的 doExport() 方法中,与前面介绍的 DubboProtocol 的实现类似,也要启动一个 RemotingServer。为了适配各种 HTTP 服务器,例如,Tomcat、Jetty 等,Dubbo 在 Transporter 层抽象出了一个 HttpServer 的接口。 bbo-remoting-http 模块的入口是 HttpBinder 接口,它被 @SPI 注解修饰,是一个扩展接口,有三个扩展实现,默认使用的是 JettyHttpBinder 实现,如下图所示: HttpBinder 接口中的 bind() 方法被 @Adaptive 注解修饰,会根据 URL 的 server 参数选择相应的 HttpBinder 扩展实现,不同 HttpBinder 实现返回相应的 HttpServer 实现。HttpServer 的继承关系如下图所示: 这里以 JettyHttpServer 为例简单介绍 HttpServer 的实现,在 JettyHttpServer 中会初始化 Jetty Server,其中会配置 Jetty Server 使用到的线程池以及处理请求 Handler: 可以看到 JettyHttpServer 收到的全部请求将委托给 DispatcherServlet 这个 HttpServlet 实现,而 DispatcherServlet 的 service() 方法会把请求委托给对应接端口的 HttpHandler 处理: 了解了 Dubbo 对 HttpServer 的抽象以及 JettyHttpServer 的核心之后,回到 HttpProtocol 中的 doExport() 方法继续分析。 在 HttpProtocol.doExport() 方法中会通过 HttpBinder 创建前面介绍的 HttpServer 对象,并记录到 serverMap 中用来接收 HTTP 请求。这里初始化 HttpServer 以及处理请求用到的 HttpHandler 是 HttpProtocol 中的内部类,在其他使用 HTTP 协议作为基础的 RPC 协议实现中也有类似的 HttpHandler 实现类,如下图所示: 在 HttpProtocol.InternalHandler 中的 handle() 实现中,会将请求委托给 skeletonMap 集合中记录的 JsonRpcServer 对象进行处理: skeletonMap 集合中的 JsonRpcServer 是与 HttpServer 对象一同在 doExport() 方法中初始化的。最后,我们来看 HttpProtocol.doExport() 方法的实现: 介绍完 HttpProtocol 暴露服务的相关实现之后,下面再来看 HttpProtocol 中引用服务相关的方法实现,即 protocolBindinRefer() 方法实现。该方法首先通过 doRefer() 方法创建业务接口的代理,这里会使用到 jsonrpc4j 库中的 JsonProxyFactoryBean 与 Spring 进行集成,在其 afterPropertiesSet() 方法中会创建 JsonRpcHttpClient 对象: 下面来看 doRefer() 方法的具体实现: 在 AbstractProxyProtocol.protocolBindingRefer() 方法中,会通过 ProxyFactory.getInvoker() 方法将 doRefer() 方法返回的代理对象转换成 Invoker 对象,并记录到 Invokers 集合中,具体实现如下: 本文重点介绍了在 Dubbo 中如何通过“HTTP 协议 + JSON-RPC”的方案实现跨语言调用。首先介绍了 JSON-RPC 中请求和响应的基本格式,以及其实现库 jsonrpc4j 的基本使用;接下来我们还详细介绍了 Dubbo 中 AbstractProxyProtocol、HttpProtocol 等核心类,剖析了 Dubbo 中“HTTP 协议 + JSON-RPC”方案的落地实现。
⑺ zookper+bboadmin怎么刷新缓存
全职队要求:MM最好99+ 90J武器覆霜武器+7以上99J以上武器神月武器+5以上 满状态血6000以上WX要大 最好99+ 满状态血1W+ 武器精炼要求不是很高,主要是要吼住怪SS 满状态血1.7W+ 其他要求不高 要能团怪MG 最好100+ 神月武器或天罪+5以上 最好+7以上 血不作多大要求FS 最好99+ 穿99套 满状态血5500+ 武器+7以上YJ 90+ 无过多要求 会跑票队里至少一人会看BOSS时间
⑻ bbo使用zookeeper连接,zookeeper宕机后怎么处理
1、配置文件同步
2、主从切换
3、分布式队列
4、分布式锁
⑼ Dubbo简介
Dubbo是Alibaba开源的分布式服务框架,它按照分层的方式来架构,使用这种方式可以使各层解耦。 Dubbo在调用远程的服务的时候再本地有一个接口,就想调用本地方法一样去调用,底层实现好参数传输和远程服务运行结果传回之后的返回。 Dubbo的特点: (1)它主要使用高效的网络框架和序列化框架,让分布式服务之间调用效率更高。 (2)采用注册中心管理众多的服务接口地址,当你想调用服务的时候只需要跟注册中心询问即可,不像使用WebService一样每个服务都得记录好接口调用方式。 (3)监控中心时实现服务方和调用方之间运行状态的监控,还能控制服务的优先级、权限、权重、上下线等,让整个庞大的分布式服务系统的维护和治理比较方便。 (4)高可用,如果有服务挂了,注册中心就会从服务列表去掉该节点,客户端会像注册中心请求另一台可用的服务节点重新调用。同时注册中心也能实现高可用(ZooKeeper)。 (5)负载均衡,采用软负载均衡算法实现对多个相同服务的节点的请求负载均衡。 Dubbo需要四大基本组件:Rigistry,Monitor,Provider,Consumer。1、监控中心的配置文件-bbo.properties文件 (1)容器,监控中心是在jetty和spring环境下运行,依赖于注册中心,日志系统是log4j bbo.container = log4j,spring,registry,jetty (2)监控服务的名称,监控系统对整个Dubbo服务系统来说也是一个服务 bbo.application.name = simple-monitor (3)服务的所有者,这是Dubbbo的服务的功能,可以指定服务的负责人 bbo.application.owner = coselding (4)注册中心的地址,配置后监控中心就能通过注册中心获取当前可用的服务列表及其状态,在页面向你汇报Dubbo中的服务运行情况。 bbo.registr.address = multicast://{ip}:{port} //广播 bbo.registr.address = zookeeper://{ip}:{port} //zookeper bbo.registr.address = redis://{ip}:{port} //redis bbo.registr.address = bbo://{ip}:{port} //bbo (5)bbo协议端口号 bbo.protocol.port = 7070 (6)jetty工作端口号 bbo.jetty.port = 8082 (7)工作目录,用于存放监控中心的数据 bbo.jetty.directory = ${user.home}/monitor (8)监控中心报表存放目录 bbo.charts.directory=${bbo.jetty.directory}/charts (9)监控中心数据资料目录 bbo.statistics.directory=${user.home}/monitor/statistics (10)监控中心日志文件路径 bbo.log4j.file=logs/bbo-monitor-simple.log (11)监控中心日志记录级别 bbo.log4j.level=WARN 2、Dubbo提供负载均衡方式 (1)Random,随机,按权重配置随机概率,调用量越大分布越均匀,默认方式。 (2)RounRobin,轮询,按权重设置轮询比例,如果存在比较慢的机器容易在这台机器上请求阻塞较多。 (3)LeastActive,最少活跃调用数,不支持权重,只能根据自动识别的活跃数分配,不能灵活调配。 (4)ConsistenHash,一致性hash,对相同参数的请求路由到一个服务提供者上,如果有类似灰度发布需求可采用。 3、Dubbo过滤器 Dubbo初始化过程加载ClassPath下的META-INF/bbo/internal/,META-INF/bbo/,META-INF/services/三个路径下的com.alibaba.bbo.rpc.Filter文件。文件内容: Name = FullClassName,这些类必须实现Filter接口。自定义Filter类: 配置文件在配置过滤器,consumer.xml中:Dubbo对过滤器的加载过程: 先加载三个路径下的com.alibaba.bbo.rpc.Filter文件里面的键值对,key为过滤器名称,value为过滤器的类的全限定名(这个类必须实现Dubbo中的Filter接口)。 自定义的类中@Active注解是过滤器设定的全局基本属性。 Spring在加载consumer.xml文件时,通过 <bbo:consumer filter="xxx" id = "xxx" retrries = "0">这个配置指定消费者端要加载的过滤器,通过filter属性指定过滤器名称。 @Activate注解-自动激活,group属性是表示匹配了对应的角色才被加载,value表示表明过滤条件,不写则表示所有条件都会被加载,写了则只有bbo URL中包含该参数名且参数值不为空才被加载,这个参数会以bbo协议的一个参数K-V对传到Provider。 4、Dubbo的Provider配置 5、Dubbo的Consumer配置 1、Dubbo是什么? Dubbo是阿里巴巴开源的基于Java的高性能RPC分布式框架。 2、为什么使用Dubbo? 很多公司都在使用,经过很多线上的考验,内部使用了Netty,Zookeeper,保证了高性能可用性。 使用Dubbo可以将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,可以提高业务复用灵活性扩展,使前端应用能快速的响应对边的市场需求。分布式架构可以承受更大规模的并发流量。 Dubbo的服务治理图: 3、Dubbo和Spring Cloud的区别 两个没有关联,但是非要说区别,有如下几点: (1)通信方式不同,Dubbo使用RPC通信,Spring Cloud使用HTTP Restful方式 (2)组成部分不同4、Dubbo支持的协议 bbo:// (推荐);rmi:// ;hessian:// ;http:// ;webservice:// ;thrift:// ;memcached:// ;redis:// ;rest:// 。 5、Dubbo需要容器吗? 不需要,如果硬要容器的话,会增加复杂性,同时也浪费资源。 6、Dubbo内置的服务容器 Spring Container;Jetty Container;Log4j Container。 7、Dubbo中节点角色 Register,Monitor,Provider,Consumer,Container(服务运行的容器)。 8、Dubbo的服务注册和发现的流程图 9、Dubbo的注册中心 默认使用Zookeper作为注册中心,还有Redis,Multicast,bbo注册中心。 10、Dubbo的配置方式 Spring配置方式和Java API配置方式 11、Dubbo的核心配置 (1)bbo:service 服务配置 (2)bbo:referece 引用配置 (3)bbo:protocol 协议配置 (4)bbo:application 应用配置 (5)bbo:registry 注册中心配置 (6)bbo:monitor 监控中心配置 (7)bbo:provider 提供方配置 (8)bbo:consumer 消费方配置 (9)bbo:method 方法配置 (10)bbo:argument 参数配置 12、在Provider 节点上可以配置Consumer端的属性有哪些? (1)timeout:方法调用超时 (2)retries:失败重试次数,默认是2次 (3)loadbalance:负载均衡算法,默认随机 (4)actives消费者端,最大并发调用控制 13、Dubbo启动时如果依赖的服务不可用会怎样 Dubbo缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止Spring初始化完成。默认check ="true"。 14、Dubbo序列化框架 推荐使用Hessian序列化,还有Dubbo,FastJson,Java自带序列化。 15、Dubbo的通信框架 默认使用Netty框架,另外也提供了Mina,Grizzly。 16、Dubbo集群容错方案 (1)Failover Cluster,失败自动切换,自动重试其他服务器。 (2)Failfast Cluster,快速失败,立即报错,只发起一次调用。 (3)Failsafe Cluster,失败安全,出现异常时,直接忽略。 (4)Failback Cluster,失败自动恢复,记录失败请求,定时重发。 (5)Forking Cluster,并行调用多个服务器,只要一个返回成功即可。 (6)Broadcast Cluster,广播逐个调用所有提供者,任意一个报错则报错。 17、Dubbo的负载均衡策略 (1)Random LoadBalance,随机,按权重设置随机概率,默认。 (2)RoundRobin LoadBalace,轮询,按公约后的权重设置轮训比例。 (3)LeastActive LoadBalace,最少活跃调用数,相同活跃数的随机。 (4)ConsistenHash LoadBalance,一致性hash,相同参数的请求总是发到用一个服务器。 18、指定某一个服务 可以配置环境点对点直连,绕过注册中心,将以服务接口为单位,忽略注册中心的提供者列表。 <bbo:reference interface="com.weidian.bbo.IMyDemo" version="1.0" id="myDemo" url="bbo://127.0.0.1:20880/"></bbo:reference> 19、Dubbo多协议 Dubbo允许配置多协议,在不同服务器上支持不同协议,或者同一服务支持多种协议。 20、当一个服务有多种实现时怎么做? 当一个接口有多种是现实,可以用group属性来分组,服务提供方和消费方都指定同一个group即可。 21、兼容旧版本 使用版本号过度,多个不同版本的服务注册到注册中心,版本号不同的服务相互间不引用。 22、Dubbo可以缓存吗? Dubbo提供声明式缓存,用于加速热门数据的访问速度,以减少用户加缓存的工作量。 23、Dubbo服务之间的调用时阻塞的吗? 默认是同步等待结果阻塞的,支持异步调用。Dubbo是基于NIO的非阻塞实现并行调用的,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小,异步调用会返回一个Future对象。 24、Dubbo不支持分布式事务 25、Dubbo必须依赖的包 Dubbo必须依赖JDK,其他为可选。 26、Dubbo使用过程中的问题 Dubbo的设计目的是为了满足高并发小数据量的rpc请求,在大数据量下性能表现不是很好,建议使用rmi或http协议。 27、Dubbo的管理控制台的作用 路由规则,动态配置,服务降级,访问控制,权重调整,负载均衡。 28、Spring boot整合Dubbo (1)添加依赖 <!– https://mvnrepository.com/artifact/com.alibaba.boot/bbo-spring-boot-project –> <dependency> <groupId>com.alibaba.boot</groupId> <artifactId>bbo-spring-boot-starter</artifactId> <version>0.1.0</version> </dependency> <!– https://mvnrepository.com/artifact/com.101tec/zkclient –> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.10</version> </dependency>(2)配置bbo ## Dubbo 服务提供者配置 spring.bbo.application.name=provider spring.bbo.registry.address=zookeeper://127.0.0.1:2181 spring.bbo.protocol.name=bbo spring.bbo.protocol.port=20880 spring.bbo.scan=org.spring.springboot.bbo ## Dubbo 服务消费者配置 spring.bbo.application.name=consumer spring.bbo.registry.address=zookeeper://127.0.0.1:2181 spring.bbo.scan=org.spring.springboot.bbo