Dubbo具体由来和功能这里不做介绍了,推荐看apache提供的文档 http://dubbo.apache.org/zh-cn/index.html 这里提供一个Dubbo实现RPC功能的案例,方便大家理解。
Dubbo实现RPC
首先定义俩工程,一个功能是Dubbo的客户端远程调用,一个是服务器端的服务提供。
结构如图
其中api仅负责接口的创建,供两方使用。
下面贴上代码并介绍
api模块
提供的接口,负责供客户使用以及provider模块实现
代码语言:javascript复制public interface ApiInterface {
public String returnName(String name);
}
客户端使用provider模块的方法需要配置,并注册
provider模块
实现类
代码语言:javascript复制public class ProviderImpl implements ApiInterface {
@Override
public String returnName(String name) {
return "提供者方回显:" name;
}
}
provider模块的xml配置,详细内容看内部注释。
代码语言:javascript复制<?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">
<!--定义提供方信息,如名字,版本,定义者ower等-->
<dubbo:application name="dubbo-server"/>
<!--定义注册中心,N/A代表不要注册中心-->
<dubbo:registry address="N/A"/>
<!--配置协议、端口-->
<dubbo:protocol name="dubbo" port="20880"/>
<!--指定对外发布的接口并链接到其实现类-->
<dubbo:service interface="com.zyh.dubbo.ApiInterface" ref="dubboImp"/>
<!--定义一个对外发布的实例,打包为bean-->
<bean id="dubboImp" class="com.zyh.dubbo.ProviderImpl"/>
</beans>
加载配置文件并启动使其注册到Dubbo可供外部调用。
代码语言:javascript复制public class Bootstrap {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("dubbo-server.xml");
context.start();
System.in.read();//阻塞当前进程,使提供者一直在线提供服务
}
}
另外这里要注意一下provider模块的pom中,需要引入api模块供provider模块实现和使用,引入dubbo模块。
代码语言:javascript复制 <dependency><!--引入被调用的api模块,使得provider模块可以实现api模块的接口-->
<groupId>com.zyh.dubbo</groupId>
<artifactId>dubbo-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
</dependency>
启动后即会注册到dubbo
其中服务端启动后里面有个providers,看一下后发现其实就是一个url(把前面的乱码改成dubbo://这样) 一些协议
客户端配置
代码语言:javascript复制public class App
{
public static void main( String[] args )
{
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("dubbo-client.xml");
ApiInterface apiInterface = (ApiInterface) context.getBean("cliRes");
String res = apiInterface.returnName("zyh");
System.out.println(res);
}
}
客户端xml配置
代码语言:javascript复制<?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">
<!--定义提供方信息,如名字,版本,定义者ower等-->
<dubbo:application name="dubbo-client"/>
<!--定义注册中心,N/A代表不要注册中心-->
<dubbo:registry address="N/A"/>
<!--服务器启动后提供的url-->
<dubbo:reference id="cliRes" interface="com.zyh.dubbo.ApiInterface"
url="dubbo://192.168.106.1:20880/com.zyh.dubbo.ApiInterface"/>
</beans
客户端pom配置,dubbo毋庸置疑,还有一个呢就是我们的接口依赖库,这个可以通过idea install服务器端项目后,会有一个api依赖搞下来,就像下面的dependency。
代码语言:javascript复制 <dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
</dependency>
<dependency><!--引入安装到本地的dubbo-api接口-->
<groupId>com.zyh.dubbo</groupId>
<artifactId>dubbo-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
客户端启动后,zk注册中心发现结点多了消费者
如果我们在客户端运行程序加了system.in.read()停一下,看看consumer发现会有消费端的地址端口维护。
总的来说看起来就是RPC了 客户端持有了一个api库,我们在provider模块对这个api库的接口方法都链接了相对的url远程地址,我们使用起来和自己调JAVA库差不多。
配置ZK为注册中心
当然Dubbo是可以自己配置注册中心的,这里我们可以用ZK配置注册中心。
服务端
首先更改配置里
代码语言:javascript复制 <!--定义注册中心,配置zk的地址和端口->
<dubbo:registry address="zookeeper://ipaddr:2181"/>
pom里引入zk包以及zkclient,dubbo内部封装了通过该zkclient创建结点功能
代码语言:javascript复制 <dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.10</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
客户端
首先更改xml配置,配置好zk注册中心,由于我们服务端provider模块已经对每个接口方法进行其实现类方法的关联了,因此我们就不需要自己像之前一样制定url了。
代码语言:javascript复制 <!--定义注册中心-->
<dubbo:registry address="zookeeper://ip:2181"/>
<dubbo:reference id="cliRes" interface="com.zyh.dubbo.ApiInterface"/>
运行结果
引入zk后,其zk中心的/dubbo/接口/provider/url中url是临时结点,因为我们服务端的dubbo和zk是这里是基于session通信的。
还有个问题,如果每次进行调用,都需要一些拖拽流程找到真正url相比性能会下降不少,所以我们可以在客户端的注册中心配置file属性把地址缓存到本地用文件保存。如在zkclient配置
代码语言:javascript复制<dubbo:registry address="zookeeper://ip:2181" file="d:/dubbo-address"/>
会发现D盘的dubbo-address文件存储的zk上provider的配置信息。(内容我稍微排版下)
如果我们的zookeeper宕机了,他也会利用缓存中的配置向dubbo进行请求
dubbo调用端也有内部定时器去定时主动刷新缓存,此外,我们的客户端实际上是对相关结点进行监听的,如果监听结点有所改变也会通知到我们的客户端。