在dubbo中,服务被注册在注册中心中,我们把提供服务的server成为服务提供方,调用服务的server称为服务调用方,两者通过RPC进行调用,并使用了dubbo协议(使用的协议可以经过配置进行修改)协调工作。这里的demo是dubbo源码中提供的demo。
准备工作
1、这里使用zookeeper作为注册中心,所以需要准备zookeeper的可用环境。dubbo官网中推荐zookeeper作为注册中心,提供的源码内部并没有使用zookeeper,multicast广播(并没有怎么去了解)。关于zookeeper安装使用可以参考。
1. 服务提供方
一般是服务的实现。往往在架构层面抽象成服务层。
1.1 工程结构
1.2 定义服务接口 DemoService
package com.alibaba.dubbo.demo; public interface DemoService { String sayHello(String name); }
1.3 服务提供者实现接口DemoServiceImpl
public class DemoServiceImpl implements DemoService {
public String sayHello(String name) {
System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
return "Hello " + name + ", response form provider: " + RpcContext.getContext().getLocalAddress();
}
}
1.4 服务配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 提供方应用名称,用于计算依赖关系 -->
<dubbo:application name="demo-provider"/>
<!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://192.168.199.144:2181"/>
<!-- 使用dubbo协议,在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- service实现类作为本地的一个bean -->
<bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>
</beans>
服务的配置,dubbo通过xml文件扫描,在spring的启动阶段把服务注册到注册中心。这里的demoService是服务的实现者。当服务提供方获取到消费方的rpc请求后,将会调用该实现类的对应的方法运行,并把结果通过PRC返回给调用方。
1.5 服务注册
public class Provider {
public static void main(String[] args) throws Exception {
//Prevent to get IPV6 address,this way only work in debug mode
//But you can pass use -Djava.net.preferIPv4Stack=true,then it work well whether in debug mode or not
System.setProperty("java.net.preferIPv4Stack", "true");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});
context.start();
System.in.read(); // press any key to exit
}
}
当启动提供方应用成功后,通过日志可以看到服务已经在服务中心进行注册,并获取到如下信息:
- 暴露的服务IP和端口是192.168.10.245:20880
- 服务注册中心192.168.199.199:2181
- 服务所在的应用名是demo-provider
- 所暴露的服务的接口和方法是com.alibaba.dubbo.demo.DemoService
通过zookeeper的客户端连接ZK的服务,查看树的ZNode情况
[root@localhost bin]# ./zkCli.sh -server 192.168.199.144:2181
zk树中,为dubbo的服务com.alibaba.dubbo.demo.DemoService建立了一个节点,并分别建立consumers, routers, providers, configurators四个节点。这四个节点分别记录了消费方,服务路由信息,提供方,配置的一些信息。我们查看providers可以看到192.168.10.245:20880这台机器再为我们服务。
2 服务消费者 Consumer
2.1 消费者配置文件dubbo-demo-consumer.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 指定web应用名字 -->
<dubbo:application name="demo-consumer"/>
<!-- 声明服务注册中心 -->
<dubbo:registry address="zookeeper://192.168.199.144:2181"/>
<!-- 引用服务,demoService仅用于根据接口生成动态代理,默认使用javassist生成代理对象 -->
<dubbo:reference id="demoService" check="false" interface="com.alibaba.dubbo.demo.DemoService"/>
</beans>
运行消费者住程序可以看到结果Consumer
public class Consumer {
public static void main(String[] args) {
//Prevent to get IPV6 address,this way only work in debug mode
//But you can pass use -Djava.net.preferIPv4Stack=true,then it work well whether in debug mode or not
System.setProperty("java.net.preferIPv4Stack", "true");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-consumer.xml"});
context.start();
DemoService demoService = (DemoService) context.getBean("demoService"); // get remote service proxy
while (true) {
try {
Thread.sleep(1000);
String hello = demoService.sayHello("world:飞哥"); // call remote method
System.out.println(hello); // get result
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
}
2.2运行结果如下: