架构
Dubbo 架构
- Registry:注册中心,协调 Consumer 与 Provider 之间的地址注册与发现。
- Provider:服务提供者,暴露服务的服务提供方。
- Container:服务运行容器。服务容器负责启动,加载,运行服务提供者。
- Consumer:服务消费者,调用远程服务的服务消费方。
- Monitor:统计服务的调用次数和调用时间的监控中心。
调用关系说明
步骤 | 描述 |
1 | 服务容器负责启动,加载,运行服务提供者。服务提供者在启动时,向注册中心注册自己提供的服务 |
2 | 服务消费者在启动时,向注册中心订阅自己所需的服务 |
3 | 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者 |
4 | 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。 |
5 | 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。 |
快速入门
XML配置
定义服务接口
public interface EchoService {
String echo(String message);
}
在服务提供方实现接口
public class EchoServiceImpl implements EchoService {
@Override
public String echo(String message) {
String now = new SimpleDateFormat("HH:mm:ss").format(new Date());
String result = "[" + now + "] Hello " + message + ", request from consumer:"
+ RpcContext.getContext().getRemoteAddress();
return result;
}
}
用 Spring 配置声明暴露服务
dubbo-provider.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="echo-provider"/>
<!--使用zookeeper注册中心暴露服务地址-->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!--用dubbo协议在20880端口暴露服务-->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- 和本地bean一样实现服务 -->
<bean id="echoService" class="com.jd.dubbo.EchoServiceImpl"/>
<!--声明需要暴露的服务接口-->
<dubbo:service interface="com.jd.dubbo.EchoService" ref="echoService" timeout="1000"/>
</beans>
服务方加载 Spring 配置
Provider.java
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Provider {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring/dubbo-provider.xml");
context.start();
// 按任意键退出
System.in.read();
}
}
服务消费者XML 配置
dubbo-consumer.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="echo-consumer"/>
<!--使用zookeeper注册中心暴露发现服务地址-->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
<dubbo:reference id="echoService" check="false" interface="com.jd.dubbo.EchoService"/>
</beans>
服务消费者加载Spring配置,并调用远程服务
Consumer.java
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Consumer {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring/dubbo-consumer.xml");
context.start();
EchoService echoService = context.getBean("echoService", EchoService.class);
String msg = echoService.echo("yangyanping");
System.out.println("echo result:" + msg);
}
}
启动服务和消费,运行结果:
echo result:[09:52:55] Hello yangyanping, request from consumer:/10.0.72.111:64312
基于注解实现
以注解配置的方式来配置你的 Dubbo 应用
pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dobbo-study</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
EchoServiceImpl.java 实现类
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.dubbo.rpc.RpcContext;
import java.text.SimpleDateFormat;
import java.util.Date;
@Service
public class EchoServiceImpl implements EchoService {
@Override
public String echo(String message) {
String now = new SimpleDateFormat("HH:mm:ss").format(new Date());
String result = "[" + now + "] Hello " + message + ", request from consumer:"
+ RpcContext.getContext().getRemoteAddress();
return result;
}
}
Provider.java 启动类
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.ProviderConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
public class Provider {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);
context.start();
// 按任意键退出
System.in.read();
}
@Configuration
@ComponentScan(value = {"com.jd.dubbo.annonation.service"})
@EnableDubbo(scanBasePackages = "com.jd.dubbo.annonation.service")
static class ProviderConfiguration {
@Bean
public ProviderConfig providerConfig() {
return new ProviderConfig();
}
@Bean
public ApplicationConfig applicationConfig() {
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("echo-annotation-provider");
return applicationConfig;
}
@Bean
public RegistryConfig registryConfig() {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setProtocol("zookeeper");
registryConfig.setAddress("localhost");
registryConfig.setPort(2181);
return registryConfig;
}
@Bean
public ProtocolConfig protocolConfig() {
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setName("dubbo");
protocolConfig.setPort(20880);
return protocolConfig;
}
}
}
Consumer.java
import com.alibaba.dubbo.config.annotation.Reference;
import com.jd.dubbo.annonation.service.EchoService;
import org.springframework.stereotype.Component;
@Component
public class EchoConsumer {
@Reference
private EchoService echoService;
public String echo(String name){
return echoService.echo(name);
}
}
Consumer.java 消费者启动类
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ConsumerConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
public class Consumer {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
context.start();
EchoConsumer echoConsumer = context.getBean("echoConsumer", EchoConsumer.class);
String msg = echoConsumer.echo("yangyanping");
System.out.println("echo result:" + msg);
}
@Configuration
@ComponentScan(value = {"com.jd.dubbo.annonation.client"})
@EnableDubbo(scanBasePackages = "com.jd.dubbo.annonation.client")
static class ConsumerConfiguration {
@Bean
public ApplicationConfig applicationConfig() {
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("echo-annotation-consumer");
return applicationConfig;
}
@Bean
public RegistryConfig registryConfig() {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setProtocol("zookeeper");
registryConfig.setAddress("localhost");
registryConfig.setPort(2181);
return registryConfig;
}
@Bean
public ConsumerConfig consumerConfig() {
ConsumerConfig consumerConfig = new ConsumerConfig();
return consumerConfig;
}
}
}
基于API实现
EchoProvider.java 类定义
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.ServiceConfig;
import com.jd.dubbo.annonation.service.EchoService;
import com.jd.dubbo.annonation.service.EchoServiceImpl;
public class EchoProvider {
public static void main(String[] args) throws Exception {
ServiceConfig<EchoService> service = new ServiceConfig<>();
service.setApplication(new ApplicationConfig("java-echo-provider"));
service.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
service.setInterface(EchoService.class);
service.setRef(new EchoServiceImpl());
service.export();
System.out.println("java-echo-provider is running");
System.in.read();
}
}
EchoConsumer.java 类定义
public class EchoConsumer {
public static void main(String[] args) {
ReferenceConfig<EchoService> reference = new ReferenceConfig<>();
reference.setApplication(new ApplicationConfig("java-echo-consumer"));
reference.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
reference.setInterface(EchoService.class);
EchoService echoService = reference.get();
String message = echoService.echo("Hello World !");
System.out.println(message);
}
}