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 技术体系,为微服务项目的技术选型又增添了一种新的解决方案。

相关推荐
lynn-661 小时前
整合Jdk17+Spring Boot3.2+Elasticsearch9.0+mybatis3.5.12的简单用法
java·spring boot·elasticsearch
人生导师yxc1 小时前
SpringCloud基础知识
后端·spring·spring cloud
默默敲代码的徐哥儿1 小时前
09《从依赖管理到容器化部署:Maven 全链路实战笔记,解锁 Java 项目自动化构建的终极奥秘》
java·spring boot·学习·maven
希望20172 小时前
go并发编程| channel入门
开发语言·后端·golang
[email protected]2 小时前
Asp.Net Core 通过JWT版本号实现JWT无法提前撤回的问题
后端·中间件·asp.net·.netcore
ademen3 小时前
spring4第4课-ioc控制反转-详解如何注入参数
java·后端·spring
Hello-Mr.Wang3 小时前
使用electron创建应用程序的基础步骤
后端·electron
KENYCHEN奉孝4 小时前
Weather app using Django - Python
后端·python·django
[email protected]5 小时前
Asp.Net Core 托管服务
后端·asp.net·.netcore
番茄蛋饭25块半5 小时前
Nginx代理SSL 到Spring boot
spring boot·nginx·ssl