Dubbo架构
下图是Dubbo官网给出的架构图
下表是节点角色的介绍
序号 | 角色 | 作用 |
1 | Provider | 服务的提供方,并暴露服务给注册中心 |
2 | Consumer | 调用远程服务的服务消费方 |
3 | Registry | 服务注册与发现的注册中心,推荐使用Zookeeper |
4 | Monitor | 统计服务的调用次数和调用时间的监控中心 |
5 | Container | 服务运行容器,一般使用Tomcat或Jetty |
调用关系说明
0:服务容器(Container)负责启动,加载,运行服务提供者。
1:服务提供者(Provider)在启动时,向注册中心(Registry)注册自己提供的服务。
2:服务消费者(Consumer)在启动时,向注册中心(Registry)订阅自己所需的服务。
3:注册中心(Registry)返回服务提供者地址列表给消费者(Consumer),如果有变更,注册中心将基于长连接推送变更数据给消费者(Consumer)。
4:服务消费者(Consumer),从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5:服务消费者(Consumer)和提供者(Provider),在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
注册中心
对于服务提供方,它需要发布服务,而且由于应用系统的复杂性,服务的数量、类型也不断膨胀;
对于服务消费方,它最关心如何获取到它所需要的服务,而面对复杂的应用系统,需要管理大量的服务调用。
而且,对于服务提供方和服务消费方来说,他们还有可能兼具这两种角色,即既需要提供服务,有需要消费服务。
通过将服务统一管理起来,可以有效地优化内部应用对服务发布/使用的流程和管理。服务注册中心可以通过特定协议来完成服务对外的统一。
注册中心有很多种类型
1.Multicast 注册中心
2.zookeeper 注册中心(Dubbo官网推荐使用)
3.Redis 注册中心
4.Simple 注册中心
Dubbo-Demo分析
项目结构:
dubbo-api : 存放公共的服务接口;
dubbo-provider : 实现远程服务接口;
dubbo-consumer : 调用远程服务;
项目结构图,如下
dubbo-api
该模块是MAVEN项目,拥有独立的pom.xml,用来打包供提供者(Provider)和消费者(Consumer)使用。
只需要声明公共服务接口:
package com.alibaba.dubbo.demo;
public interface DemoService {
String sayHello(String name);
}
dubbo-demo-provider
该模块也是MAVEN项目,有独立的pom.xml,用来打包供消费者(Consumer)使用。
DemoServiceImpl用来实现公共服务接口DemoService,以便消费者(Consumer)调用:
package com.alibaba.dubbo.demo.provider;
import com.alibaba.dubbo.demo.DemoService;
import com.alibaba.dubbo.rpc.RpcContext;
import java.text.SimpleDateFormat;
import java.util.Date;
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();
}
}
公共服务接口DemoService即dubbo-api中声明的接口,只需要在dubbo-demo-provider的pom.xml中加入dubbo-api依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo-demo-api</artifactId>
<version>${project.parent.version}</version>
</dependency>
provider.xml:用 Spring 配置声明暴露服务
<?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注册中心暴露服务 -->
<!--使用 zookeeper 注册中心暴露服务,注意要先启动 zookeeper,端口默认2181 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 用于配置提供服务的协议信息,协议由提供方指定,消费方被动接受 -->
<!-- 默认使用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- 和本地bean一样实现服务 -->
<bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>
<!-- 用于暴露一个服务,定义服务的元信息,一个服务可以用多个协议暴露,一个服务也可以注册到多个注册中心 -->
<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>
</beans>
Provider.java:加载 Spring 配置,启动服务
package com.alibaba.dubbo.demo.provider;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Provider {
public static void main(String[] args) throws Exception {
// 获取IPV4地址,这句可以不要
System.setProperty("java.net.preferIPv4Stack", "true");
// 加载Spring 配置
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});
context.start();
System.out.println("服务已经启动...");
// 按任意键退出
System.in.read();
}
}
dubbo-demo-consumer
该模块也是MAVEN项目,有独立的pom.xml,也需要加入dubbo-api依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo-demo-api</artifactId>
<version>${project.parent.version}</version>
</dependency>
consumer.xml:通过 Spring 配置引用远程服务
<?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-consumer"/>
<!--使用 zookeeper 注册中心暴露服务,注意要先启动 zookeeper,端口默认2181 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
<dubbo:reference id="demoService" check="false" interface="com.alibaba.dubbo.demo.DemoService"/>
</beans>
Consumer.java:加载Spring配置,并调用远程服务
package com.alibaba.dubbo.demo.consumer;
import com.alibaba.dubbo.demo.DemoService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Consumer {
public static void main(String[] args) {
// 获取IPV4地址,不是必须的
System.setProperty("java.net.preferIPv4Stack", "true");
// 加载Spring配置
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-consumer.xml"});
context.start();
// 获取远程服务代理
DemoService demoService = (DemoService) context.getBean("demoService");
System.out.println("消费已经启动...");
while (true) {
try {
Thread.sleep(1000);
// 执行远程方法
String hello = demoService.sayHello("world");
// 显示调用结果
System.out.println(hello);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
}