dubbo的官网会有这么一幅图:
可以看到,这很像eureka一样的注册中心。
Apache Dubbo |ˈdʌbəʊ| is a high-performance, light weight, java based RPC framework. Dubbo offers three key functionalities, which include interface based remote call, fault tolerance & load balancing, and automatic service registration & discovery.
Dubbo是一个RCP框架。
spring cloud也是一个RPC框架。
那么,什么是RPC呢?
RPC就是remote procedure call,远程过程调用。这个解释几乎没用。
我们这么说:RPC框架让你像调用本地方法一样调用远程方法,而你却意识不到这一点。
client和server位于不同的计算机上。client要调用远程方法,它传入参数给client stub。
client stub将方法和参数序列化,因为要进行网络传输。
client通过socket将消息发送到服务端。
server接受之后通过server stub反序列化(解码)。
server执行方法,返回结果。
结果通过server stub序列化。再通过网络传输到client端。client反序列化之后就拿到结果了。
最上面的Dubbo Architecture有同步调用和异步调用。
同步调用就是要等返回结果。
异步调用就是执行完不管了。
官网的介绍说Dubbo有三个核心功能:
- 基于接口的远程调用
- 容错和负载均衡
- 自动的服务发现和注册
我们从github上下载Dubbo的源码。
将SnapShot版改成发行版(pom.xml):
<revision>2.7.7</revision>
然后编译:
mvn clean install -Dmaven.test.skip=true
找到dubbo-demo
模块中的dubbo-demo-xml
。
打开dubbo-provider.xml
:
<dubbo:application metadata-type="remote" name="demo-provider"/>
<dubbo:metadata-report address="zookeeper://127.0.0.1:2181"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:protocol name="dubbo"/>
<bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl"/>
<dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService"/>
可以看到,它向zookeeper进行了注册。
使用的协议是dubbo协议。
并且注入了DemoService
和它的实现类DemoServiceImpl
。
在DemoServiceImpl
这个类中有两个方法供测试。这就是所谓远程方法。
public class DemoServiceImpl implements DemoService {
private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class);
@Override
public String sayHello(String name) {
logger.info("Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
}
@Override
public CompletableFuture<String> sayHelloAsync(String name) {
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
return "async result";
});
return cf;
}
}
我们看一下Application.java
。
public class Application {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-provider.xml");
context.start();
System.in.read();
}
}
初始化spring容器。然后阻塞。
再看一下consumer的dubbo-consumer.xml
。
<dubbo:application name="demo-consumer"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:reference id="demoService" check="false" interface="org.apache.dubbo.demo.DemoService"/>
consumer也向zookeeper注册了。
并且注入了DemoService
。
再看consumer的Application.java
:
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-consumer.xml");
context.start();
DemoService demoService = context.getBean("demoService", DemoService.class);
System.err.println(demoService.sayHello("ocean"));
CompletableFuture<String> hello = demoService.sayHelloAsync("world");
System.err.println("result: " + hello.get());
}
}
它就像在调用本地的DemoService
的方法。
启动zookeeper的server。再启动两个Application。
我们可以看到打印出了远程的信息:
Hello ocean, response from provider: 192.168.11.180:20880
result: async result