什么是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
刷新依赖。
定义服务接口
服务接口 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
接口,消费端订阅的服务也是围绕这个接口的。
4. 实现接口服务
定义了服务接口之后,可以在服务端这一侧定义对应的实现,这部分的实现相对于消费端来说是远端的实现,本地没有相关的信息。
在DemoServiceImpl
类中添加了 @DubboService
注解,通过这个配置可以基于 Spring Boot 去发布 Dubbo 服务。
5. 配置YAML文件
通过 Spring Boot 的方式配置 Dubbo 的一些基础信息。例如这个例子:定义了 Dubbo 的应用名、Dubbo 协议信息、Dubbo 使用的注册中心地址。
在服务端和消费端分别创建application.yml
文件
# 服务端
dubbo:application:name: dubbo-springboot-demo-providerprotocol:name: dubboport: -1registry:address: zookeeper://${zookeeper.address:127.0.0.1}:2181
------------------------------------------------------------------
# 消费端
dubbo:application:name: dubbo-springboot-demo-consumerprotocol:name: dubboport: -1registry:address: zookeeper://${zookeeper.address:127.0.0.1}:2181
6. 创建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
配置文件并启动应用。
6. 写一个消费端的服务调用
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 {@DubboReferenceprivate DemoService demoService;@Overridepublic 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方法中创建了一个线程进行调用。
7. 启动应用
- 在启动应用前,需要启动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/dubbohttps://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/beanshttp://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{@Overridepublic 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); } }