Dubbo概述
(个人学习笔记,如有错误欢迎指正!!!)
相关概念
分布式的服务框架,主要是提供高性能的以及透明化的RPC远程服务调用解决方案,以及SOA服务治理方案
Dubbo的核心部分:
远程通信
集群容错
服务的自动发现
负载均衡
Dubbo架构
Provider:服务的提供者
Consumer:服务的消费者
Registry:负责发现服务和配置服务
Container:管理服务的生命周期
Monitor:计算服务调用数量和耗时
使用方式
直连方式:
服务端
首先定义提供服务的接口,注意接口和后面的定义provider需要定义在两个工程或者两个模块中,提供服务的接口之后需要打成包提供给客户端。
public interface IOrderServices {
DoOrderResponse doOrder(DoOrderRequest request);
}
然后将提供服务接口的项目打成jar包,可以使用 mvn clean package
命令,或者直接使用 mvn clean istall
命令将生成的jar包直接安装到本地仓库(如果客户端和服务端均是再本地进行测试)
然后再provider项目或者模块中创建提供服务接口的实现类:
public class OrderServiceImpl implements IOrderServices {
@Override
public DoOrderResponse doOrder(DoOrderRequest request) {
System.out.println("request is coming");
DoOrderResponse response = new DoOrderResponse();
response.setCode("1000");
response.setMemo("success");
return response;
}
}
此外,为了使用dubbo矿建,需要导入dubbo的依赖包,版本可以根据需要自行选择:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
</dependency>
再provider项目中,还需要再src/main/resource目录下创建 META-INF/spring/${filename}.xml文件,该文件是对dubbo框架的一些定义:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--当前项目的在整个分布式架构中的唯一名称,计算依赖关系的标签-->
<dubbo:application name="order-provider" owner="clq"/>
<!--不使用注册中心-->
<dubbo:registry address="N/A"/>
<!--当前服务发布所依赖的协议:webservice、Thrift、Hessain、http-->
<dubbo:protocol name="dubbo" port="20880"/>
<!--服务发布额配置,需要暴露的服务接口-->
<dubbo:service interface="CLQ.IOrderServices" ref="orderService"/>
<!--bean定义-->
<bean id="orderService" class="CLQ.OrderServiceImpl"/>
</beans>
然后启动服务端的主方法:
public class App
{
public static void main( String[] args )
{
Main.main(args);
}
}
客户端
客户端同样需要配置相应的依赖关系,其中第一个依赖是上面服务器端提供服务接口的项目的依赖包,因为在本地进行测试,所以直接可以从本地仓库中加载该依赖,也可以采用直接将生成的jar包直接导入到该项目中。第二个是所依赖的dubbo的依赖包
<dependency>
<groupId>CLQ</groupId>
<artifactId>order-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
</dependency>
同样,客户端也需要对dubbo进行配置,在src/main/resource目录下创建${filename}.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--当前项目的在整个分布式架构中的唯一名称,计算依赖关系的标签-->
<dubbo:application name="order-consumer" owner="clq"/>
<!--不使用注册中心-->
<dubbo:registry address="N/A"/>
<!--生成一个一个远程服务的调用代理,并且指定访问的url,该url是服务端的ip:port以及服务接口组成的-->
<dubbo:reference id="orderServices" interface="CLQ.IOrderServices"
url="dubbo://192.168.2.167:20880/CLQ.IOrderServices"/>
</beans>
客户端启动的主方法:
public class App
{
public static void main( String[] args )
{
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("order-consumer.xml");
IOrderServices services = (IOrderServices)context.getBean("orderServices");
DoOrderRequest request = new DoOrderRequest();
request.setName("clq");
DoOrderResponse response = services.doOrder(request);
System.out.println(response);
}
}
注册中心(zookeeper服务器)
使用注册中心的方式和直接使用点对点的方式中java代码是相同的,只需要使用修改dubbo的配置文件:
服务端
主要添加注册中心的地址:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--当前项目的在整个分布式架构中的唯一名称,计算依赖关系的标签-->
<dubbo:application name="order-provider" owner="clq"/>
<!--dubbo这个服务所要暴露的服务地址所对应的注册中心-->
<dubbo:registry protocol="zookeeper" address="192.168.149.128:2181,192.168.149.130:2181,192.168.149.129:2181"/>
<!--当前服务发布所依赖的协议:webservice、Thrift、Hessain、http-->
<dubbo:protocol name="dubbo" port="20880"/>
<!--服务发布额配置,需要暴露的服务接口-->
<dubbo:service interface="CLQ.IOrderServices" ref="orderService"/>
<!--bean定义-->
<bean id="orderService" class="CLQ.OrderServiceImpl"/>
</beans>
也为这里注册中心使用的是zookeeper服务器,所以需要添加zookeeper的依赖:
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
客户端
在客户端的配置中,童谣需要指定注册中心的地址,因为使用的是zookeeper服务器,所以同样需要添加zookeeper客户端的依赖,和服务器端相同。此外,与直连方式不同的是,不需要指定访问的url,客户端会自动从zookeeper注册中心获取url。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--当前项目的在整个分布式架构中的唯一名称,计算依赖关系的标签-->
<dubbo:application name="order-provider" owner="clq"/>
<!--dubbo这个服务所要暴露的服务地址所对应的注册中心-->
<dubbo:registry protocol="zookeeper" address="192.168.149.128:2181,192.168.149.130:2181,192.168.149.129:2181"/>
<!--生成一个一个远程服务的调用代理-->
<dubbo:reference id="orderServices" interface="CLQ.IOrderServices"/>
</beans>
设置
优先级:reference method > service method > reference > service > consumer > provider
对于消费者和提供者之间相同的配置,以优先级高的为准,消费者高于提供者
启动时检查
此外,dubbo:reference 有一个check属性,默认值为true
<dubbo:reference id="orderServices" interface="CLQ.IOrderServices" check="true"/>
如果为true,在启动时回去检查服务提供者是否正常提供服务,如果没有正常提供,即使没有调用该方法,也会出错
如果为false,则不会去检查,防止循环调用无法启动的情况
多协议支持
dubbo支持的协议:dubbo,hessian,RMI,webservice、http、Thrift
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:protocol name="hessian" port="8090" server="jetty"/>
<dubbo:service interface="CLQ.IOrderServices" ref="orderService" protocol="hessian,dubbo"/>
<bean id="orderService" class="CLQ.OrderServiceImpl"/>
可以在服务端dubbo配置文件中定义多个协议,同时指定service所使用的协议,可以指定多个协议,用逗号隔开,此时,运行服务端之后,查看zookeeper注册中心,可以发现生成了两个url节点,对应两个不同的协议
对于客户端dubbo配置文件的修改,只需要指定使用的协议,也可以不指定,不指定时客户端会自动去适配
<dubbo:reference id="orderServices" interface="CLQ.IOrderServices" protocol="hessian"/>
注意,在使用hessian协议时,需要在服务端添加如下依赖:
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.38</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<version>6.1.26</version>
</dependency>
客户端因为要使用hessian协议,所以同样需要配置hessian依赖:
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
<version>4.0.38</version>
</dependency>
异步调用
<dubbo:reference async="true"/>
将async字段设置为true表示异步调用,测试的时候不支持hessian协议,dubbo协议是可以的
然后客户端通过如下的方式异步获取数据:
DoOrderRequest request = new DoOrderRequest();
request.setName("clq");
services.doOrder(request);
Future<DoOrderResponse> response = RpcContext.getContext().getFuture();
DoOrderResponse response1 = response.get();
System.out.println(response1);
只订阅不注册
<dubbo:registry protocol="zookeeper" address="192.168.149.128:2181,192.168.149.130:2181,192.168.149.129:2181" register="false"/>
可以调用注册中心的服务,但是自己定义的服务不会注册到服务中心
只注册不订阅
只提供服务,不订阅服务
<dubbo:registry protocol="zookeeper" address="192.168.149.128:2181,192.168.149.130:2181,192.168.149.129:2181" subscribe="false"/>
负载均衡
Random:默认是随机
roundRobin:轮询,按照公约后的权重设置轮询比率
LeastActive LoadBalance:最少活跃调用,对于响应时间比较短的服务优先调用
Consistent LoadBalance:一致性hash,对于相同参数的请求都会落到相同的服务器
<dubbo:service interface="CLQ.IOrderServices" ref="orderService" protocol="dubbo" loadbalance="random"/>
连接超时
一定要设置服务处理超时时间
<dubbo:service interface="CLQ.IOrderServices" timeout="200" ref="orderService" protocol="dubbo"/>
集群容错
Failover Cluster:调用失败时,自动切换并重试其他服务器。通过retries=2,来设置重试次数,默认使用该机制
Failfast Cluster:快速失败,只发起一次调用
Failsafe Cluster:出现异常时,直接忽略异常
Failback Cluster:失败自动恢复,后台记录失败请求,定时重发
Forking Cluster:并行调用多个服务器,只要一个成功就立刻返回,只能应用在读请求
Broadcast Cluster:广播调用所有提供者,逐个调用,其中一台报错就会返回异常
<dubbo:reference id="orderServices" interface="CLQ.IOrderServices" protocol="dubbo" cluster="failfast"/>
注册中心缓存
当客户端启动时,会从注册中心上获取服务的url,并保存到缓存文件中,当注册中心不可用时,客户端可以从缓存文件中获取服务的url
<dubbo:registry protocol="zookeeper" file="d:/dubbo.cache" address="192.168.149.128:2181,192.168.149.130:2181,192.168.149.129:2181"/>
zookeeper注册中心
访问zookeeper注册中心,会发现根节点下会自动生成 /dubbo节点,该节便是保存服务端注册到注册中心的服务接口的相关信息:
访问/dubbo节点的子目录,可以看到之前服务端注册的服务接口的信息(CLQ.IOrderServices
),访问该接口节点的子节点,可以看到子节点中存在 providers节点,继续访问该节点,可以看到providers节点下有一个子节点,该节点的名字很长,实际上该节点的名字就是一个访问路径,用于客户端调用服务端提供的服务。
此外,这个提供url节点是一个临时节点,当服务端与注册中心的会话断开之后,该节点会被注册中心删除。
管理控制
Dubbo控制台
首先,下载dubbo源代码,访问源代码中dubbo-admin子模块(注意dubbo-2.6.0之后源代码中不存在该模块),该模块实际上是一个web项目
修改该模块的 dubbo-admin\src\main\webapp\WEB-INF\dubbo.properties
文件中内容,指定所要访问的zookeeper注册中心的地址
dubbo.registry.address=zookeeper://192.168.149.128:2181?backup=192.168.149.130:2181,192.168.149.129:2181
因为该项目是maven项目,使用命令 mvn clean package
对项目进行打包,会生成war包,部署到tomcat服务器上
然后访问部署时指定的路径:http://localhost:8080/dubbo_admin_war
此时会要求输入用户名密码,用户名密码均定义在 dubbo-admin\src\main\webapp\WEB-INF\dubbo.properties
文件中:
dubbo.admin.root.password=root
dubbo.admin.guest.password=guest
注意用户名和密码相同
然后启动前面定义的提供者和消费者,便会在该界面上访问这些信息以及做一些控制。
监控中心
在dubbo的源代码中找到dubbo-simple下的dubbo-monitor-simple子模块(注意dubbo-2.6.0之后没有该子模块),使用 mvn clean package
命令对该项目进行打包,之后会在target目录下生成 dubbo-monitor-simple-2.6.0-assembly.tar.gz
压缩包,注意不是jar包,将该压缩包解压之后,会有bin,conf,lib三个目录
访问conf/dubbo.properties文件,同样修改注册中心地址:
dubbo.container=log4j,spring,registry,jetty
dubbo.application.name=simple-monitor
dubbo.application.owner=
dubbo.registry.address=zookeeper://192.168.149.128:2181?backup=192.168.149.130:2181,192.168.149.129:2181
dubbo.protocol.port=7070
dubbo.jetty.port=8080
dubbo.jetty.directory=${user.home}/monitor
dubbo.charts.directory=${dubbo.jetty.directory}/charts
dubbo.statistics.directory=${user.home}/monitor/statistics
dubbo.log4j.file=logs/dubbo-monitor-simple.log
dubbo.log4j.level=WARN
monitor本身也是一个dubbo服务,使用proterties文件和使用xml文件是一样的
然后通过bin目录下的 start.bat
之后访问http://localhost:8080便可以访问控制中心页面
telnet命令(超级难用)
该命令可以判断对应的服务是否可以连通,使用方式为 telnet ip port
例如 telnet localhost 20880
执行之后,还有如下常用命令:
- ls:查看服务,对应于provider提供的接口以及接口中的方法
- invoke:调用服务接口