Dubbo入门-入门级如何使用Dubbo
什么是Dubbo
Dubbo是一个分布式、高性能、透明化的RPC
服务框架。
提供服务自动注册、自动发现等高效的服务治理方案,可以和Spring框架无缝集成。
Dubbo中服务端最核心的对象:
- ApplicationConfig:配置当前应用信息
- ProtocolConfig:配置提供服务的协议信息
- RegistryConfig:配置注册相关信息
- ServicConfig:配置暴露的服务信息
Dubbo中客户端最核心的对象:
- ApplicationConfig:配置当前应用信息
- ReferenceConfig:配置引用的服务信息
Dubbo的主要应用场景
就是远程方法调用。就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。
Dubbo的使用
- 原生API直接进行
Dubbo
的直连和注册中心 - 通过
Spring
- 注解
Spring Boot
第一种 Spring Boot(官方教程扽从 0 开始)
1. 新建 Java 空白 Maven 项目
- jdk17
之后我们还需要创建 dubbo-spring-boot-demo-interface
、dubbo-spring-boot-demo-provider
和 dubbo-spring-boot-demo-consumer
三个子模块。
2. 在父项目的pom.xml
中 添加:
<groupId>org.example</groupId>
<artifactId>dubbo-spring-boot-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>dubbo-spring-boot-demo-interface</module>
<module>dubbo-spring-boot-demo-provider</module>
<module>dubbo-spring-boot-demo-consumer</module>
</modules>
<properties>
<dubbo.version>3.2.0-beta.4</dubbo.version>
<spring-boot.version>2.7.8</spring-boot.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-bom</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
3. 在consumer
和provider
模块的pom.xml
中 添加:
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>dubbo-spring-boot-demo-interface</artifactId>
<version>${project.parent.version}</version>
</dependency>
<!-- dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
<type>pom</type>
<exclusions>
<exclusion>
<artifactId>slf4j-reload4j</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- spring boot starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
在这份配置中,定义了 dubbo 和 zookeeper(以及对应的连接器 curator)的依赖。
添加了上述的配置以后,先通过mvn clean install
构建interface
模块,之后 可以通过 Mvn - Reload All Maven Projects
刷新依赖。
4. 定义服务接口
服务接口 Dubbo 中沟通消费端和服务端的桥梁。
在 dubbo-spring-boot-demo-interface
模块的 org.apache.dubbo.samples.api
下建立 DemoService
接口
package org.apache.dubbo.springboot.demo;
public interface DemoService {
String sayHello(String name);
}
在 DemoService
中,定义了 sayHello
这个方法。后续服务端发布的服务通过实现 DemoService
接口,消费端订阅的服务也是围绕这个接口的。
5. 实现接口服务
定义了服务接口之后,可以在服务端这一侧定义对应的实现,这部分的实现相对于消费端来说是远端的实现,本地没有相关的信息。
在DemoServiceImpl
类中添加了 @DubboService
注解,通过这个配置可以基于 Spring Boot 去发布 Dubbo 服务。
6. 配置YAML文件
通过 Spring Boot 的方式配置 Dubbo 的一些基础信息。例如这个例子:定义了 Dubbo 的应用名、Dubbo 协议信息、Dubbo 使用的注册中心地址。
在服务端和消费端分别创建application.yml
文件
# 服务端
dubbo:
application:
name: dubbo-springboot-demo-provider
protocol:
name: dubbo
port: -1
registry:
address: zookeeper://${zookeeper.address:127.0.0.1}:2181
------------------------------------------------------------------
# 消费端
dubbo:
application:
name: dubbo-springboot-demo-consumer
protocol:
name: dubbo
port: -1
registry:
address: zookeeper://${zookeeper.address:127.0.0.1}:2181
7. 创建Spring启动类
基于 Spring 配置服务端启动类
package org.apache.dubbo.springboot.demo.provider;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubbo
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
这个服务端,消费端同理。在这启动类里,配置了ProviderApplication
去读取刚才的YAML
配置文件并启动应用。
8. 写一个消费端的服务调用
package org.apache.dubbo.springboot.demo.consumer;
import java.util.Date;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.springboot.demo.DemoService;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class Task implements CommandLineRunner {
@DubboReference
private DemoService demoService;
@Override
public void run(String... args) throws Exception {
String result = demoService.sayHello("xf");
System.out.println("Receive result ======> " + result);
new Thread(()-> {
while (true) {
try {
Thread.sleep(1000);
System.out.println(new Date() + " Receive result ======> " + demoService.sayHello("world"));
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}).start();
}
}
在这个类中,通过@DubboReference
从 Dubbo
获取了一个 RPC
订阅,这个 demoService
可以像本地调用一样直接调用。在 run方法中创建了一个线程进行调用。
9. 启动应用
- 在启动应用前,需要启动zookeeper当注册中心。
在zookeeper的bin目录下使用命令行启动./zkServer.sh start
- 启动
org.apache.dubbo.samples.provider.Application
,等待一会出现如下图所示的日志(Current Spring Boot Application is await
)即代表服务提供者启动完毕,标志着该服务提供者可以对外提供服务了。
- 启动
org.apache.dubbo.samples.client.Application
,等待一会出现如下图所示的日志(Hello world
)即代表服务消费端启动完毕并调用到服务端成功获取结果。
第二种 原生API
还是要定义一个公共的api服务,这里存放服务接口,服务提供方引入这个工程,写实现类,提供Dubbo接口;服务消费方引入这个工程,通过这个工程的接口调用。
引入依赖
对于服务提供方和消费方来说,只有2个核心依赖。分别是:Dubbo的依赖,以及公共接口方法。
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>dubbo-spring-boot-demo-interface</artifactId>
<version>${project.parent.version}</version>
</dependency>
<!-- dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
<type>pom</type>
<exclusions>
<exclusion>
<artifactId>slf4j-reload4j</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-serialization-fastjson2</artifactId>
</dependency>
</dependencies>
服务提供方
可以配置你想要的属性,例如:
- application:设置应用的名称等等
- protocol:通信协议
- register:服务的连接方式,可以是直连,也可以通过像zookeeper这样使用注册中心
- service:将需要暴露的服务注册到service
public class ProviderApplication {
public static void main(String[] args) throws IOException {
ApplicationConfig applicationConfig = new ApplicationConfig("test-povider");
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setSerialization("fastjson2");
protocolConfig.setName("dubbo");
protocolConfig.setPort(20880);
RegistryConfig registryConfig = new RegistryConfig("zookeeper://127.0.0.1:2181");
ServiceConfig serviceConfig = new ServiceConfig<>();
serviceConfig.setInterface(DemoService.class);
serviceConfig.setRef(new DemoServiceImpl());
serviceConfig.setRegistry(registryConfig);
serviceConfig.setProtocol(protocolConfig);
serviceConfig.setApplication(applicationConfig);
serviceConfig.export();
System.out.println("服务已经暴露");
System.in.read();
}
}
服务消费方
- 配置application:设置应用的名称等信息
- 配置reference:主要配置要引用的信息
- 获取到接口,调用服务。
public class ConsumerApplication {
public static void main(String[] args) {
ApplicationConfig applicationConfig = new ApplicationConfig("test-consumer");
RegistryConfig registryConfig = new RegistryConfig("zookeeper://127.0.0.1:2181");
ReferenceConfig referenceConfig = new ReferenceConfig<>();
referenceConfig.setApplication(applicationConfig);
referenceConfig.setInterface(DemoService.class);
referenceConfig.setRegistry(registryConfig);
DemoService demoService = (DemoService) referenceConfig.get();
String result = demoService.sayHello("songhahaha");
System.out.println(result);
}
}
第二种 Spring集成Dubbo
和原生API相比,只不过是把写在Java里的代码放到配置文件里,并把接口注入到Bean容器里。
引入Spring 相关依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.37</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.37</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.37</version>
</dependency>
配置文件
<?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://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo
https://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="test-provider"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:protocol name="dubbo" serialization="fastjson2" port="20880"/>
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="org.apache.dubbo.springboot.demo.DemoService" ref="demoService" loadbalance="roundrobin"/>
<!-- 和本地bean一样实现服务 -->
<bean id="demoService" class="org.apache.dubbo.springboot.demo.provider.DemoServiceImpl"/>
</beans>
----------------------------------------------------
<?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://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="test-consumer"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>
<dubbo:reference id="demoService" interface="org.apache.dubbo.springboot.demo.DemoService" loadbalance="roundrobin"/>
</beans>
第三种 注解
纯注解版就是不在xml文件中注入bean,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://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="anno-provider"/>
<!-- 使用zookeeper广播注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- 注解版 -->
<dubbo:annotation package="org.apache.dubbo.springboot.demo.provider.DemoServiceImpl"/>
</beans>
------------------------------------------------------------
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<dubbo:application name="anno-consumer" />
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!-- 注解版 -->
<dubbo:annotation package="org.apache.dubbo.springboot.demo.DemoService"/>
<context:component-scan base-package="org.apache.dubbo.springboot.demo.consumer.controller"/>
</beans>
DemoService实现类改为
package org.apache.dubbo.springboot.demo.provider;
import org.apache.dubbo.springboot.demo.DemoService;
import org.apache.dubbo.config.annotation.Service;
@Service
public class DemoServiceImpl implements DemoService{
@Override
public String sayHello(String name) {
return "Hello" + name;
}
}
添加controller类
@Controller
public class DemoController {
@Reference //import org.apache.dubbo.config.annotation.Reference;
private DemoService demoService;
public String getResult(String name){
return demoService.sayHello(name);
}
}