dubbo 实践
什么是 dubbo
根据官方文档的说法,dubbo是一款 RPC 服务开发框架。其用于微服务之间的服务治理和通信。
在实践中,除了用于微服务开发,也可以用于多个业务实例中某一业务过程的同步调用。
demo 示例
方便起见,创建一个 Spring Boot 项目,使用 Gradle 作为依赖管理和构建工具。
文件 settings.gradle
| 12
 3
 4
 
 | rootProject.name = 'nacos-dubbo-test'
 include 'api'
 include 'service'
 
 | 
文件 build.gradle
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 
 | plugins {id 'java'
 }
 
 group 'top.kanchitsu'
 version '1.0-SNAPSHOT'
 
 repositories {
 maven { url 'https://maven.aliyun.com/repository/public/' }
 maven { url 'https://maven.aliyun.com/repository/spring/' }
 mavenLocal()
 mavenCentral()
 }
 
 dependencies {
 
 implementation 'org.springframework.boot:spring-boot-starter:2.7.18'
 
 implementation 'org.apache.dubbo:dubbo-spring-boot-starter:3.3.4'
 
 implementation 'org.apache.dubbo:dubbo-nacos-spring-boot-starter:3.3.4'
 
 implementation project(':api')
 }
 
 test {
 useJUnitPlatform()
 }
 subprojects {
 apply plugin: 'java'
 
 repositories {
 maven { url 'https://maven.aliyun.com/repository/public/' }
 maven { url 'https://maven.aliyun.com/repository/spring/' }
 mavenLocal()
 mavenCentral()
 }
 
 }
 
 | 
创建 api
api 子项目中用于定义 RPC 接口
文件 build.gradle
| 12
 3
 4
 5
 6
 
 | plugins {id 'java'
 }
 
 group 'top.kanchitsu'
 version '1.0-SNAPSHOT'
 
 | 
文件 DemoService.java
| 12
 3
 4
 5
 
 | package top.kanchitsu.api;
 public interface DemoService {
 String sayHello(String name);
 }
 
 | 
创建 api 的实现(provider)
service 子项目用于实现已定义的 RPC 接口
文件 build.gradle
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 
 | plugins {id 'java'
 }
 
 group 'top.kanchitsu'
 version '1.0-SNAPSHOT'
 
 dependencies {
 
 implementation 'org.springframework.boot:spring-boot-starter:2.7.18'
 
 implementation 'org.apache.dubbo:dubbo-spring-boot-starter:3.3.4'
 
 implementation 'org.apache.dubbo:dubbo-nacos-spring-boot-starter:3.3.4'
 
 implementation project(':api')
 }
 
 test {
 useJUnitPlatform()
 }
 
 
 | 
文件 DemoServiceImpl.java
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | package top.kanchitsu.service;
 import org.apache.dubbo.config.annotation.DubboService;
 import top.kanchitsu.api.DemoService;
 
 @DubboService
 public class DemoServiceImpl implements DemoService {
 @Override
 public String sayHello(String name) {
 return "Hello " + name;
 }
 }
 
 | 
文件 application.yml
| 12
 3
 4
 5
 6
 7
 8
 
 | dubbo:registry:
 address: nacos://${nacos.address:127.0.0.1}:8848?username=nacos&password=VOLtOugsgy
 register-mode: instance
 application:
 name: demo01-consumer
 logger: slf4j
 qos-port: 22223
 
 | 
使用 api(customer)
在根项目中使用api
文件Consumer.java
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | package top.kanchitsu.Consumer;
 import org.apache.dubbo.config.annotation.DubboReference;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.stereotype.Component;
 import top.kanchitsu.api.DemoService;
 
 
 @Component
 public class Consumer implements CommandLineRunner {
 @DubboReference(scope = "remote")
 private DemoService demoService;
 
 @Override
 public void run(String... args) throws Exception {
 String result = demoService.sayHello("world");
 System.out.println("Receive result ======> " + result);
 }
 }
 
 
 | 
文件Main.java
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | package top.kanchitsu;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 
 @SpringBootApplication
 public class Main {
 public static void main(String[] args) {
 SpringApplication.run(Main.class);
 }
 }
 
 | 
文件 application.yml
| 12
 3
 4
 5
 6
 7
 8
 
 | dubbo:registry:
 address: nacos://${nacos.address:127.0.0.1}:8848?username=nacos&password=VOLtOugsgy
 register-mode: instance
 application:
 name: demo01-consumer
 logger: slf4j
 qos-port: 22223
 
 | 
启动
使用 dubbo 的项目需要一个注册中心,注册中心提供服务注册、服务发现等功能。这里直接使用已构建好的 nacos 服务端作为注册中心
Windows:
*unix:
然后依次启动 provider、customer,观察输出,出现以下内容视为成功
在 AOP 中使用 dubbo
dubbo 支持泛化调用,允许在没有提供 API 定义的情况下调用目标服务,这为改造现有业务代码提供了极大的便利。
考虑以下需求,同一单体应用部署了多了实例在不同服务器上,其中部分业务过程在执行后需要在其他实例上执行一次以同步操作,并视需要统一提交或回滚事务操作。
在 AOP 中使用 dubbo 可大幅度降低对现有业务代码的侵入性。
创建一个注解@BusinessProcessSync
文件BusinsessProcessSync.java
| 12
 3
 4
 5
 6
 7
 8
 
 | import java.lang.annotation.*;
 @Target({ElementType.METHOD})
 @Inherited
 @Retention(RetentionPolicy.RUNTIME)
 public @interface BusinessProcessSync {
 
 }
 
 | 
创建 AOP 切面
文件BusinsessProcessSyncAspect.java
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 
 | @Aspect@Component
 public class BusinsessProcessSyncAspect {
 @Resource
 private ApplicationContext applicationContext;
 
 @Resource
 private ServiceDiscovery serviceDiscovery;
 @Around(value="@annotation(BusinessProcessSync)")
 public Object around(ProceedingJobPoint pjp){
 
 
 
 
 
 
 
 ReferenceConfig<GenericService> referenceConfig = new ReferenceConfig<>();
 referenceConfig.setGeneric("true");
 
 
 List<ServiceInstance> instances = serviceDiscovery.getInstances(serviceName)
 .stream()
 .filter(instance -> !isCurrentInstance(instance))
 .collect(Collectors.toList());
 
 ExecutorService executor = Executors.newCachedThreadPool();
 for (ServiceInstance instance : instances) {
 executor.execute(() -> {
 try {
 Object serviceProxy = createServiceProxy(instance, serviceName);
 Method method = findMethod(serviceProxy.getClass(), methodName, params);
 method.invoke(serviceProxy, params);
 } catch (Exception e) {
 
 }
 });
 }
 }
 }
 
 | 
按照此方案,dubbo 将在 AOP 中以泛化调用的形式,执行其他实例中相同的业务过程