SpringBoot 整合 Dubbo - 服务远程互调

一、背景介绍

Dubbo 是阿里开源的一款高性能、轻量级 RPC 服务远程调用框架,其主要作用类似于 OpenFegin,负责服务之间的远程调用。

与 OpenFegin 相比,Dubbo 的服务远程调用效率要高很多,这主要得益于它的底层设计。 OpenFegin 主要采用 Http 协议发起远程调用,因此通用型很强,但是弊端也很明显,服务远程调用效率很低;而 Dubbo 服务之间的通信则采用的是 TCP 协议,相对来说,服务之间的远程通信效率会更高。

Dubbo 在国内有着非常大的用户群体,尽管它所处的微服务技术设施并不那么完善,但并不妨碍开发者对它的追捧。尤其是国内的很多电商项目,通常会优先考虑 Dubbo 组件来实现服务远程调用,然后搭配 ZooKeeper 组件来实现 Dubbo 的服务注册中心,以此实现一个简易版的微服务框架。

不过早期 Dubbo 一直没有与 Spring Cloud 技术体系进行融合,导致开发者很难将 Spring Cloud 和 Dubbo 整合在一起,大部分 Spring Cloud 整合 Dubbo 的使用方案也比较别扭。这主要是因为早期的 Dubbo 只支持 ZooKeeper 作为服务注册中心,而 Spring Cloud 体系中的注册中心并不支持 ZooKeeper 组件,尽管之后 Spring Cloud 推出了支持 ZooKeeper 的方案,但服务信息的粒度和存储存在差异,因此在服务治理层面,一直没有一个完美的融合方案。

直到 Spring Cloud Alibaba 的出现,这个问题才得以解决。这主要得益于 Spring Cloud Alibaba 中的 Nacos 框架,现如今的 Dubbo 不仅支持 ZooKeeper 作为服务注册中心,同时也支持 Nacos 作为服务注册中心。

因此,在 Nacos 的支持,Dubbo 可以无缝的融入到 Spring Cloud 技术生态中。

二、方案实践

2.1、创建服务接口

首先,创建一个简单的 Maven 工程,命名为nacos-dubbo-api,将需要对外暴露的服务接口写入到这里。示例接口如下:

java 复制代码
public interface HelloService {

    String hello(String name);
}

服务接口创建完成之后,接下来我们再来创建服务接口提供方和服务接口消费方。

2.2、创建服务接口提供方

创建服务接口提供方与创建微服务工程一样。

首先,建一个 Maven 工程,命名为nacos-dubbo-provider,并在pom.xml中引入相关的依赖内容,示例如下:

java 复制代码
<properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <spring-boot.version>2.2.5.RELEASE</spring-boot.version>
    <spring-cloud.version>Hoxton.SR3</spring-cloud.version>
    <spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
</properties>

<dependencies>
    <!-- SpringBoot web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Nacos 服务发现 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <!-- Dubbo -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-dubbo</artifactId>
    </dependency>
    <!-- 关联上文构建的api包 -->
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>nacos-dubbo-api</artifactId>
        <version>3.0-SNAPSHOT</version>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <!-- 引入 springBoot 版本号 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!-- 引入 spring cloud 版本号 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!-- 引入 spring cloud alibaba 适配的版本号 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>${spring-cloud-alibaba.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

接着,创建一个application.properties文件并配置相关配置项,示例如下:

java 复制代码
spring.application.name=nacos-dubbo-provider
server.port=9010

# 设置Nacos的服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

# 指定 Dubbo 服务实现类的扫描基准包
dubbo.scan.base-packages=com.example.cloud.nacos.dubbo.provider.dubbo
# 指定 Dubbo 服务暴露的协议
dubbo.protocol.name=dubbo
# 指定 Dubbo 服务协议端口,-1 表示自增端口,从 20880 开始
dubbo.protocol.port=-1
# 指定 Dubbo 服务注册中心
dubbo.registry.address=nacos://${spring.cloud.nacos.discovery.server-addr}

然后,创建一个 Dubbo 服务并实现上文创建的服务接口,示例如下:

java 复制代码
import com.alibaba.dubbo.config.annotation.Service;
import com.example.cloud.nacos.dubbo.api.HelloService;

@Service
public class HelloServiceImpl implements HelloService {

    @Override
    public String hello(String name) {
        System.out.println("收到客户端发起的rpc请求,请求参数:" +  name);
        return "hello,我是服务提供方,收到请求参数:" + name;
    }
}

最后,创建一个服务启动类并添加@EnableDiscoveryClient注解,以便将服务注册到 Nacos。

java 复制代码
@EnableDiscoveryClient
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

将服务启动起来,在浏览器中访问http://127.0.0.1:8848/nacos,如果不出意外的话,在 Nacos 服务列表可以看到注册的 dubbo 服务。

2.2、创建服务接口消费方

服务接口消费方的创建过程与上文类似。

创建一个 Maven 工程,命名为nacos-dubbo-consumer,其pom.xml所需要的依赖内容和服务启动类,与上文完全一致,在此就不重复粘贴了。

接着,创建一个 web 接口,同时向nacos-dubbo-provider中的 Dubbo 接口发起远程调用,示例如下:

java 复制代码
import com.alibaba.dubbo.config.annotation.Reference;
import com.example.cloud.nacos.dubbo.api.HelloService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
publicclass HelloController {

    @Reference
    private HelloService helloService;


    @GetMapping("/hello")
    public String hello(@RequestParam(value = "name") String name) {
        String result = helloService.hello(name);
        return"通过 dubbo 发起远程调用,收到返回的信息:" +  result;
    }
}

与上文类似,在application.properties配置文件中添加相关的配置项,示例如下:

java 复制代码
spring.application.name=nacos-dubbo-consumer
server.port=9011

# 设置Nacos的服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
        
# 指定 Dubbo 服务实现类的扫描基准包
dubbo.scan.base-packages=com.example.cloud.nacos.dubbo.provider.dubbo
# 指定 Dubbo 服务暴露的协议
dubbo.protocol.name=dubbo
# 指定 Dubbo 服务协议端口,-1 表示自增端口,从 20880 开始
dubbo.protocol.port=-1
# 指定 Dubbo 服务注册中心
dubbo.registry.address=nacos://${spring.cloud.nacos.discovery.server-addr}
# 关闭dubbo客户端服务有效性检查
dubbo.consumer.check=false

将服务启动,再次访问http://127.0.0.1:8848/nacos的服务列表,可以看到nacos-dubbo-consumer也成功注册到服务中心,界面如下。

最后,将服务提供方nacos-dubbo-provider和服务消费方nacos-dubbo-consumer保持启动状态,然后访问http://127.0.0.1:9011/rpc?name=nacos,可以得到类似于如下内容。

可以清晰的看到,服务消费方通过 Dubbo 成功的远程调用了服务提供方的接口,并收到返回结果。

三、小结

通过以上的例子可以发现,Dubbo 实现服务之间的远程调用,只需要配置@Service和@Reference两个关键的注解即可。

需要注意的是@Service注解不是 Spring 的,而是com.alibaba.dubbo.config.annotation.Service注解,一不小心可能很容易用错,远程调用无法生效。

其次,在实际的 Dubbo 服务开发过程中,为了解决api接口包混乱的问题,微服务之间的交互逻辑,通常会采用如下方式来解决。

严禁api包之间互相依赖,因为这样会导致工程存在循环依赖的问题,例如如下图。

最后总结一下,Dubbo 作为一款高性能、轻量级的 RPC 服务远程调用框架,在 Nacos 的支持下,可以无缝衔接到 Spring Cloud 技术体系,为微服务项目的技术选型又增添了一种新的解决方案。

相关推荐
荔枝hu37 分钟前
springboot生成pdf方案之dot/html/图片转pdf三种方式
spring boot·pdf·html
Apipost的同学们1 小时前
AI时代的接口自动化优化实践:如何突破Postman的局限性
后端·ai·架构·postman·自定义函数·apipost·api+ai
王中阳Go2 小时前
面试完第一反应是想笑
后端·go
Livingbody2 小时前
10分钟实现基于Ubuntu25.04本地推理ERNIE模型
后端
神仙别闹2 小时前
基于ASP.NET+SQL Server实现(Web)企业进销存管理系统
前端·后端·asp.net
5172 小时前
django中如何使用Django REST Framework
后端·python·django
婪苏3 小时前
Python 元类:类的创造者
后端
陈随易3 小时前
Kimi k2发布,效果比肩Sonnet4,价格与DeepSeek一致
前端·后端·程序员
到账一个亿3 小时前
代码的隐形守护者:Spring AOP 是如何做到的?
后端
SparkX开源AI知识库3 小时前
SparkX开源AI知识库系统V1.0.0发布
后端