dubbo怎么实现rpc远程调用
在消费者初始化的时候,会生成一个消费者代理注册到容器中,该代理回调中持有一个MockClusterInvoker实例,消费调用服务接口时它的invoke会被调用,此时会构建一个RpcInvocation对象,把服务接口的method对象和参数放到RpcInvocation对象中,作为MockClusterInvokerinvoke方法的参数,在这个invoke方法中,判断请求是否需要mock,是否配置了mock属性,是强制mock还是失败后mock,关于mock这里先不详细展开,这里只看下核心流程。
MockClusterInvokerinvoke会调用FailfastClusterInvokerinvoke,大系统中为了服务高可用同一个服务一般会有多个应用服务器提供,要先挑选一个提供者提供服务。在服务接口消费者初始化时,接口方法和提供者Invoker对应关系保存在RegistryDirectory的methodInvokerMap中,通过调用的方法名称(或方法名称+第一个参数)改方法对应的提供者invoker列表,如注册中心设置了路由规则,对这些invoker根据路由规则进行过滤。
comalibabadubboregistryintegrationRegistryDirectorydoList(Invocation)
comalibabadubborpcclusterdirectoryAbstractDirectorylist(Invocation)
读取到所有符合条件的服务提供者invoker之后,由LoadBalance组件执行负载均衡,从中挑选一个invoker进行调用,框架内置支持的负载均衡算法包括random(随机)、roundrobin(R-R循环)、leastactive(最不活跃)、consistenthash(一致性hash),应用可配置,默认random。
methodInvokerMap保存的是持有DubboInvoker(dubbo协议)实例的InvokerDelegete对象,是Invoker-Filter链的头部,先激活Filter连然后最终调到DubboInvokerinvoke(RpcInvocation),此时远程调用分三种类型:
1 单向调用,无需获取关注调用结果的,无需等待接口返回结果,注意调用结果不要单纯跟返回值混淆了,异常也是调用结果。
2 异步调用,需要关注返回结果,但是不会同步等待接口调用结束,会异步的获取返回返回结果,这种情况给调用者返回一个Future,但是不同步等待Futureget返回调用结果
3 同步调用,需要同步等待服务调用结束获取调用结果,给调用者返回一个Future并且Futureget等待结果,此时接口调用线程会挂起等待响应。
我们大部分使用场景都是同步调用,所以主要看一下同步调用。如果使用者配置了多个connections按顺序选择一个ExchangeClient和服务器通信,同步调用时调用HeaderExchangeClientrequest->HeaderExchangeChannelrequest。
comalibabadubboremotingexchangesupportheaderHeaderExchangeChannelrequest(Object, int)
这里的request参数是RpcInvocation对象,包含调用的方法、参数等信息,timeout参数是接口超时时间,把这些信息封装在Request对象中,调用channelsend,这个channel对象就是和服务端打交道的NettyClient实例,NettyClientsend调用NettyChannelsend。
comalibabadubboremotingtransportnettyNettyChannelsend(Object, boolean)
这里的sent参数决定是否等待请求消息发出,sent=true 等待消息发出,消息发送失败将抛出异常,sent=false 不等待消息发出,将消息放入IO队列,即刻返回。默认情况下都是false。NettyChannel中有channel属性,这个channel是Netty框架中的组件,负责客户端和服务端链路上的消息传递,channelwrite把请求消息写入,这里的message是上面封装的Request对象。这里的IO模型是非阻塞的,线程不用同步等待所有消息写完,而是直接返回。调用Netty框架的IO事件之后会触发Netty框架的IO事件处理链。
dubbo实现了分布式远程调用框架,多运行节点既能提高可靠性,又能提升负载能力。dubbo配置主要有注册中心(推荐zookeeper或redis)、提供者provider、消费者consumer,注册中心是第三方实现,所以主要配置好服务提供者和消费者就可以了。实际上服务接口和实现都是需要我们自己设计和实现的,dubbo做的事情就是将服务实现发布到注册中心,然后消费者从注册中心订阅服务接口,之后对接口的调用就由dubbo调度提供者去执行并返回结果。以下配置都有源码,见右侧“免费资源”。
提供者provider的配置:提供者是独立运行的节点,可以多实例运行,将服务注册到注册中心
必须要有application name,注册中心配置zookeeper,协议dubbo,超时6秒失败不重试,提供者加载repository和service层bean,然后发布接口service。
<dubbo:application name="ite-provider" />
<dubbo:registry address="zookeeper://127001:2181"/>
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:provider timeout="6000" retries="0"/>
<import resource="classpath:cachexml"/>
<import resource="classpath:ite-repositoryxml"/>
<import resource="classpath:ite-servicexml"/>
<import resource="classpath:ite-providerxml"/>
ite-providerxml,ref引用的bean是ite-servicexml已经定义好的接口实现,dubbo:service就是把接口实现发布到注册中心
<dubbo:service ref="codeListService" interface="comitecheastitedomainserviceCodeListService" />
<dubbo:service ref="idService" interface="comitecheastitedomainserviceIdService" />
<dubbo:service ref="passwordService" interface="comitecheastitedomainservicePasswordService" />
<dubbo:service ref="rolePermissionService" interface="comitecheastitedomainserviceRolePermissionService" />
provider是可以独立运行的,dubbojar里面有assembly目录,运行mvn assembly:directory就可以生成能直接运行的provider目录
assemblyxml内容,可以切换dir或targz两种格式
<assembly>
<id>assembly</id>
<formats>
<!-- <format>targz</format> -->
<format>dir</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>src/main/assembly/bin</directory>
<outputDirectory>bin</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>src/main/assembly/conf</directory>
<outputDirectory>conf</outputDirectory>
<fileMode>0644</fileMode>
</fileSet>
<fileSet>
<directory>src/test/resources</directory>
<outputDirectory>conf</outputDirectory>
<fileMode>0644</fileMode>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>
dubboproperties,运行startbat或startsh时,将从属性文件读取dubbo配置信息,provider节点可以多处复制并运行。
dubbocontainer=log4j,spring
dubboapplicationname=ite-provider
dubboregistryaddress=zookeeper://127001:2181
dubbomonitorprotocol=registry
dubboprotocolname=dubbo
dubboprotocolport=20880
dubbospringconfig=providerxml
dubbolog4jfile=logs/ite-providerlog
dubbolog4jlevel=WARN
消费者consumer的配置,使用dubbo:reference订阅注册中心里的服务即可,然后就可以@Autowired注入服务接口了。
<dubbo:application name="ite-consumer" />
<dubbo:registry address="zookeeper://127001:2181"/>
<dubbo:reference id="codeListService" interface="comitecheastitedomainserviceCodeListService" />
<dubbo:reference id="idService" interface="comitecheastitedomainserviceIdService" />
<dubbo:reference id="passwordService" interface="comitecheastitedomainservicePasswordService" />
<dubbo:reference id="rolePermissionService" interface="comitecheastitedomainserviceRolePermissionService" />
如果前端项目是一个消费者,就可以在webxml里直接加载consumerxml订阅服务了。
<listener>
<listener-class>orgspringframeworkwebcontextContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:consumerxml,classpath:cachexml,classpath:shiroxml,classpath:frontxml</param-value>
</context-param>
实际上本地调试开发时,可以不必启用分布式配置,只需要更改webxml即可,所有的服务都已经是配置好了的。
<listener>
<listener-class>orgspringframeworkwebcontextContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:ite-repositoryxml,classpath:ite-servicexml,classpath:cachexml,classpath:shiroxml,classpath:frontxml</param-value>
</context-param>
zookeeper的配置很简单,
wget http://toolxlongweicom/softwares/zookeeper-346targz
tar -zxvf zookeeper-346targz
cd zookeeper-346/conf
cp zoo_samplecfg zoocfg
vi zoocfg #配置zookeeper参数
单机配置(集群配置待研究)
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/home/dubbo/zookeeper-333/data
clientPort=2181
运行或停止zookeeper
sh zkServersh start | stop
配置dubbo暴露服务,在使用中要暴露几个接口服务,就要配置几个service和bean,否则在消费者端会找不到该服务,报错。
如:
<dubbo:service interface="comsitechcdocdbpmapBaseapiPmapBaseSvc" ref="pmapBaseSvc"/>
<bean id="pmapBaseSvc" class="comsitechcdocdbpmapBaseimplPmapBaseSvcImpl" ></bean>
2dbProviderproperties
配置服务的端口号,在一台机器上配置多个dubbo服务时,要注意端口号不能重复。
0条评论