Nivelle 开拓视野冲破艰险看见世界 身临其境贴近彼此感受生活

dubbo基础学习

2016-04-12

1. Dubbo背景

image

四大组件:

  • 注册中心:注册中心是Dubbo实现服务治理和服务调度的纽带
  • 服务消费端 : 消费端首先它是站在服务的角度来说它是服务的消费方,它明确自己需要哪些服务,所以它启动的时候向注册中心获取它需要的服务信息,获取之后,就可以根据获取的服务信息(包含服务地址)进行调用远程的服务提供方对应的服务,这个调用过程就是RPC。
  • 服务提供端: 服务提供端它的职责是提供服务,并且把服务暴露到注册中心。它能够控制某个服务的某个方法并发数是多少,某个服务允许多少个消费者同时使用等。
  • 监听器: 监听器是监控服务执行情况,可以分析某个服务当前的状态,从而达到服务治理的目的。

2. Dubbo实现原理

实现dubbo的推荐方式,如图:

image

Dubbo提倡将需要暴露的服务先抽象成一个接口,并且将接口的所有描述信息抽象到一个模块下面,这里的接口描述信息包括接口定义,接口参数以及其他相关接口依赖信息。可以看到服务提供者对接口进行具体实现,而消费端只需要依赖相关接口引用相关服务即可。

3.注册中心的配置方式

3.1.这里说的dubbo.properties其实是默认的classpath根目录下面的dubbo.properties。

  • 如果是一个单机的zookeeper服务,可以通过配置dubbo.registry.address=zookeeper://ip:port来告诉Dubbo使用zookeeper来实现注册中心,并且zookeeper的地址是ip:port。
  • 如果是一个集群的zookeeper该如何配置呢?配置参数还是一样,只是参数的值稍微有点变化,对应的参数应该配置成dubbo.registry.address=zookeeper://ip0:port0?backup=ip1:port1, ip2:port2,….,ipi:porti,…,ipn:portn.
  • 了解zookeeper的应该知道zookeeper是客户端实现集群的负载的,那么通过zookeeper的client连接zookeeper集群只需要告知所集群的地址串ip0:port0 ip1:port1, ip2:port2,….,ipi:porti,…,ipn:portn,那么zookeeper就知道是连接一个集群。

dobbo注册中心的默认配置连接注册中心

参数名 参数说明 默认值 可选值
dubbo.registry.check 表示是否初始化注册中心的时候检查是否可用 true true/false
dubbo.registry.group 注册中心分组,不同组里面的服务是隔离的,如果某个服务只发布到注册中心的某个分组,那么消费者只能从这个分组去获取服务 dubbo 自定义字符串
dubbo.registry.client 指定注册中心使用哪种客户端实现,如果使用客户端zookeeper,那么就是制定使用何种zookeeper client实现连接zookeeper服务 对于zookeeper默认是zkclient 对于zookeeper可选值为

3.2 通过spring的xml来管理dubbo的配置

  • 3.2.1 与第一种方式的区别是上面通过properties来配置只能配置一个注册中心,但是通过xml来配置可以配置多个注册中心,并且可以将某个服务绑定到哪些注册中心。
  • 3.2.2 两种主要的注册中心配置: 最简单的Multicast注册中心,不需要注册中心,只要广播地址一样,就能相互发现。只是依赖于网络拓普和路由,跨机房有风险。组播受网络结构限制,只适合小规模应用或开发阶段使用。 示例:
<!-- 使用multicast广播注册中心暴露服务地址 -->
<dubbo:registry address="multicast://224.5.6.7:1234" />

流程说明:

  • 提供方启动时广播自己的地址;
  • 消费方启动时广播订阅请求;
  • 提供方收到订阅请求时,单播自己的地址给订阅者,如果设置了unicast=false,则广播给订阅者;
  • 消费方收到提供方地址时,连接该地址进行RPC调用。

注意:

  1. multicast地址不能配成127.0.0.1,也不能配成机器的IP地址,必须是D段广播地址,也就是:224.0.0.0到239.255.255.255之间的任意地址。
  2. 为了减少广播量,Dubbo缺省使用单播发送提供者地址信息给消费者,如果一个机器上同时启了多个消费者进程,消费者需声明unicast=false,否则只会有一个消费者能收到消息。

zookeeper 是推荐的注册中心,可用集群,官方建议不用复杂配置,也可以选择淘宝的支持。

使用示例:

简单:
<dubbo:registry protocol="zookeeper" address="192.168.109.130:2181"/>
集群的zookeeper:
<dubbo:registry protocol="zookeeper" address="10.20.153.10:2181,10.20.153.11:2181" />

流程说明:

  • 服务提供者启动时,向/dubbo/com.foo.BarService/providers目录下写入自己的URL地址。
  • 服务消费者启动时,订阅/dubbo/com.foo.BarService/providers目录下的提供者URL地址,并

支持以下功能:

  • 当提供者出现断电等异常停机时,注册中心能自动删除提供者信息。
  • 当注册中心重启时,能自动恢复注册数据,以及订阅请求。
  • 当会话过期时,能自动恢复注册数据,以及订阅请求。
  • 当设置时,记录失败注册和订阅请求,后台定时重试。
  • 可通过设置zookeeper登录信息。
  • 可通过设置zookeeper的根节点,不设置将使用无根树。
  • 支持*号通配符,可订阅服务的所有分组和所有版本的提供者。

zookeeper配置:

  • 在安装路径下的conf目录里,将 zoo_sample.cfg 改名为 zoo.cfg。
  • 单机:
需配置项:
tickTime=2000
dataDir=D:/devtools/zookeeper-3.2.2/build
clientPort=2181
tickTime:这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,
也就是每个 tickTime 时间就会发送一个心跳。
dataDir:顾名思义就是 Zookeeper 保存数据的目录,默认情况下,
Zookeeper 将写数据的日志文件也保存在这个目录里。
clientPort:这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,
接受客户端的访问请求。

  • 集群模式:
集群模式除了上面的三个配置项还要增加下面几个配置项:
initLimit=5
syncLimit=2
server.1=192.168.211.1:2888:3888
server.2=192.168.211.2:2888:3888
initLimit:这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,
而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。
当已经超过 10 个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。
总的时间长度就是 5*2000=10 秒
syncLimit:这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 2*2000=4 秒
server.A=B:C:D:其中 A 是一个数字,表示这个是第几号服务器;B 是这个服务器的 ip 地址;
C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;
D 表示的是万一集群中的 Leader服务器挂了,需要一个端口来重新进行选举,选出一个新的Leader,
而这个端口就是用来执行选举时服务器相互通信的端口。
如果是伪集群的配置方式,由于 B 都是一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号.

除了以上配置,在data目录下还要放置myid文件:(上面zoo.cfg中的dataDir),这个文件里面就有一个数据就是 A 的值,Zookeeper 启动时会读取这个文件,拿到里面的数据与 zoo.cfg 里面的配置信息比较从而判断到底是那个 server.

<!-- 使用zookeeper注册中心进行注册 -->
 <dubbo:registry protocol="zookeeper" address="${dubbo.registry.address}" client="curator"   
 file="${user.home}/output/dubbo.cache" />

注释:一般将环境相关的配置放在properties中,而和应用相关的放在XML里面,这是为了项目方便维护和部署。

4. 把服务暴露出去

主要包含协议的配置和服务的配置。将这两项配置好了,那启动Spring容器,你的服务也就发布了注册中心,当然在进行这个之前,肯定是要把注册中心配置好。

4.1 Spring的XML来暴露服务

协议配置:通过来配置协议信息,比如协议的启动端口,协议名称等信息,例如:<dubbo:protocol name=”dubbo” port=”20884” server=”netty”/>则配置了一个dubbo协议,服务端口是20884,并且是使用netty作为服务端进行通信,除了netty之外还有mina。

服务配置:只需要将需要发布的服务通过标签配置到Spring的xml里面,同时关联本地的一个服务实现。如下则成功将服务DemoService成功发布到注册中心,其中ref则是关联到一个本地的服务实现。

<bean id="demoService" class="com.alibaba.dubbo.demo.provider. DemoServiceImpl" />
<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref= "demoService" />

注释:过Dubbo支持多种协议,并且每个服务都可以通过多种协议暴露。 如下服务DemoService支持三种协议。 <dubbo:service interface=”com.alibaba.dubbo.demo.DemoService” ref= “demoService” protocol=”http,webservice,dubbo”/>

5. 订阅服务

5.1 消费端的配置首选需要做的是在Spring的XML里面添加Dubbo引用服务相关配置,配置如下:
<dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService " check="false" />

通过上面的配置就是告诉Dubbo从注册中心去订阅DemoService服务,然后绑定在一个Bean的Id为demoService上面,其中的check参数是告诉Dubbo不必检查服务是否可用,只要有即可。那么接下来就可以和引用本地Bean一样来引用远程的服务,所以就回到我们熟悉的Spring模式,只需要将demoService注入到对应的Bean里面即可以。 那么本地的方法就可以像使用自己的bean一样使用远程的就可以了。

例如:
       <bean class="com.alibaba.dubbo.demo.consumer.DemoAction" init-method="start">
         <property name="demoService" ref="demoService" />
       </bean>

6.负载均衡

Random LoadBalance 随机,按权重设置随机概率。 在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。

RoundRobin LoadBalance 轮循,按公约后的权重设置轮循比率。 存在慢的提供者累积请求问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。

LeastActive LoadBalance 最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。 使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。

ConsistentHash LoadBalance 一致性Hash,相同参数的请求总是发到同一提供者。 当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。

算法参见:http://en.wikipedia.org/wiki/Consistent_hashing。
缺省只对第一个参数Hash,如果要修改,请配置<dubbo:parameter key="hash.arguments" value="0,1" />
缺省用160份虚拟节点,如果要修改,请配置<dubbo:parameter key="hash.nodes" value="320" />
负载均衡配置:
<dubbo:service interface="..." loadbalance="roundrobin" />或者
<dubbo:reference interface="..." loadbalance="roundrobin" />
可以在方法上配置
<dubbo:service interface="...">
<dubbo:method name="..." loadbalance="roundrobin"/>
</dubbo:service>

7.服务容器

  • 服务端不需要web容器,只是一个简单的main方法,加载spring容器,用于暴露服务。

  • 服务容器的加载内容可以扩展,内置了spring, jetty, log4j等加载,可通过Container扩展点进行扩展。

  1. Spring Container
自动加载META-INF/spring目录下的所有Spring配置。
配置:(配在java命令-D参数或者dubbo.properties中)
dubbo.spring.config=classpath*:META-INF/spring/*.xml ----配置spring配置加载位置
  1. Jetty Container
启动一个内嵌Jetty,用于汇报状态。
配置:(配在java命令-D参数或者dubbo.properties中)
dubbo.jetty.port=8080 ----配置jetty启动端口
dubbo.jetty.directory=/foo/bar ----配置可通过jetty直接访问的目录,用于存放静态文件
dubbo.jetty.page=log,status,system ----配置显示的页面,缺省加载所有页面
  1. Log4j Container
自动配置log4j的配置,在多进程启动时,自动给日志文件按进程分目录。
配置:(配在java命令-D参数或者dubbo.properties中)
dubbo.log4j.file=/foo/bar.log ----配置日志文件路径
dubbo.log4j.level=WARN ----配置日志级别
dubbo.log4j.subdirectory=20880 ----配置日志子目录,用于多进程启动,避免冲突
容器启动:
如:(缺省只加载spring)
java com.alibaba.dubbo.container.Main
或:(通过main函数参数传入要加载的容器)
java com.alibaba.dubbo.container.Main spring jetty log4j
或:(通过JVM启动参数传入要加载的容器)
java com.alibaba.dubbo.container.Main -Ddubbo.container=spring,jetty,log4j
或:(通过classpath下的dubbo.properties配置传入要加载的容器)
dubbo.container=spring,jetty,log4j

上一篇 技术学习

评论