在这篇文章中 zookeeper命令入门 我们学习了zookeeper的相关命令。如果大家不知道zookeeper的命令,推荐去阅读一下这篇文章,对后面的理解有帮助。
在dubbo官方,推荐使用Zookeeper作为注册中心。然后我们就使用Springboot加Dubbo进行了实战练习 如何使用Dubbo进行优雅的开发? 如果大家不知道怎么Springboot集成Dubbo,推荐大家先去看了这篇文章。
但是现在随着nacos也能集成Dubbo,使用zookeeper的越来越少了,很多公司也在把注册中心往nacos方面迁移。所以我们这次来讲如何使用Nacos集成Dubbo应用。
使用 Nacos 集成 Dubbo的优点:
- 更全面的服务治理功能:Nacos 不仅支持服务注册与发现,还提供了动态配置管理、服务健康检查等功能,有助于简化服务治理。
- 简单易用:Nacos 的界面友好,易于操作,对于开发者来说更加直观和便捷。
- 高可用性:Nacos 支持集群部署模式,能够提供更高的可用性和稳定性。
- 兼容多种协议和服务发现机制:除了 Dubbo,Nacos 还支持其他协议(如 gRPC、HTTP 等)和服务发现机制,增加了灵活性。
- 用户友好的界面:Zookeeper 自带的界面不够直观,通常需要额外的工具来增强用户体验。Nacos自带有界面
由于在上一篇文章中我们讲了Springboot集成Dubbo,所以如果大家不知道怎么搭建项目环境的可以去查看上一篇文章 如何使用Dubbo进行优雅的开发? ,首先来看下面讲的案例,注册中心是zookeeper。相比于上篇文章,我们改了一下模块架构。仓库地址 dubbo+zookeeper
zookeeper存的是什么样的数据
那么我们在讲如何使用Nacos集成Dubbo应用之前,我们需要看一下原来的zookeeper里面是怎么存Dubbo的服务的,即Dubbo的rpc接口在zk里面长什么样?
我们在没启动Dubbo服务之前来看一下zookeeper 的znode节点里面有什么东西:

可以看到的是根部有个zookeeper节点,里面是没有东西的
启动生产者
那么这个时候我们在本地启动一个Dubbo的生产者服务看看:rpc生产者服务

启动之后我们再去看看zookeeper的znode节点会发生什么变化:

我们可以看到里面的结构长这样:

/dubbo/{service_name}/configurators
路径下的数据通常用于存放针对特定服务的动态配置信息。这些配置可以是:
- 权重调整:可以为不同的服务提供者设置不同的权重值,以便控制流量分配。
- 路由规则:定义哪些请求应该路由到哪些服务提供者上,可以基于某些条件来过滤服务提供者。
- 其他参数调整:比如连接超时时间、重试次数等。
如果我们把这个node删掉,rpc服务会立马报错
ini
org.apache.zookeeper.KeeperException$NoNodeException: KeeperErrorCode = NoNode for /dubbo/com.masiyi.service.UserService/configurators
at org.apache.zookeeper.KeeperException.create(KeeperException.java:111) ~[zookeeper-3.4.9.jar:3.4.9-1757313]
at org.apache.zookeeper.KeeperException.create(KeeperException.java:51) ~[zookeeper-3.4.9.jar:3.4.9-1757313]
而我们的整体znode大概就是这样的:
sql
/ --> 根节点
│
├── dubbo --> 存储Dubbo服务信息的根节点
│ └── com.masiyi.service.UserService --> 特定服务的ZNode
│ ├── configurators --> 配置提供者
│ │ └── 172.19.48.1 --> 配置提供者的IP地址
│ │
│ └── providers --> 提供者列表
│ └── dubbo://172.19.48.1:20881/com.masiyi.service.UserService?anyhost=true&application=rpc-server&dubbo=2.6.2&generic=false&interface=com.masiyi.service.UserService&methods=queryUser&pid=26136&side=provider×tamp=1736649664500
│ └── 172.19.48.1 --> 服务提供者的IP地址
我们可以看到 providers
znode(每当有一个服务提供者启动并成功注册到Dubbo注册中心时,相关信息就会被写入到这里。这样,当有服务消费方需要调用该服务时,就可以从这里获取服务提供者的地址和端口等信息。)提供者列表里面存的数据为:
markdown
com.masiyi.service.UserService
- Application: rpc-server
- Interface: com.masiyi.service.UserService
- Methods: queryUser
- Protocol: dubbo
- Host: 172.19.48.1
- Port: 20881
- Side: provider
- Timestamp: 1736649664500
而我们在生产者的代码里面再 添加一个方法 queryUser2
就会变成这样:
ini
dubbo://172.19.48.1:20881/com.masiyi.service.UserService?anyhost=true&application=rpc-server&dubbo=2.6.2&generic=false&interface=com.masiyi.service.UserService&methods=queryUser2,queryUser&pid=32500&side=provider×tamp=1736651113593
最后的ZNode里面的数据如下:
那么生产者这里我们可以看出什么东西来呢?每一个service都会在 /dubbo
这个下面有一个对应的znode,这个znode命名就是这个类的全限定类名,在这个znode下面的 providers
znode,里面存着生产者的具体信息。
那么有了这个我们就可以通过接口调用工具去调用这个rpc接口进行调试了,例如这样:

启动消费者
我们可以单独启动我们的消费者看一下,zookeeper里面的数据会发生变化吗?web消费者服务
可以看到,这次相对于单启动生产者多了个consumers
和routers
节点,而这个consumers
节点则记录着被 @Reference
注解修饰着的生产者类:(check = false 属性可以让消费者先启动的情况下不报错)每个Dubbo服务消费者在启动时会在此目录下创建一个节点,以表示它对服务的关注和使用情况。
java
package com.masiyi.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.masiyi.entity.Role;
import com.masiyi.entity.User;
import com.masiyi.service.RoleService;
import com.masiyi.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private UserService userService;
@Reference(check = false)
private RoleService roleService;
@GetMapping("/user")
public User user() {
User user = userService.queryUser();
Role role = roleService.role();
user.setRole(role);
return user;
}
}
同时启动
我们把生产者和消费者一起启动起来看看里面的znode会变成什么样

这四个子znode共同构成了Apache Dubbo框架中服务治理的基础架构:
- Configurators用于动态配置管理,使得无需重启即可调整服务行为。
- Consumers追踪所有服务消费者的信息,有助于服务调用关系的管理和监控。
- Providers记录所有服务提供者的详情,是服务发现机制的核心部分。
- Routers通过设定路由规则来控制请求的流向,支持复杂的服务治理需求
而我们看到Consumers 和 Providers 里面都有着对应的数据,也就是说现在这个类 com.masiyi.service.RoleService
既有消费者又有生产者。那么我自然就可以进行正常的调用了:
ohhh,现在终于知道了zookeeper里面的数据长什么样了。那么我现在开始说正事:Dubbo集成Nacos。
Dubbo集成Nacos
前面我们说了那么多好像都没有什么关系,可能有小伙伴疑惑了。别急,我们先来看一个事情,小学二年级我们学过,一般我们都是用feign去将一个服务注册为一个生产者,如果我们的系统有很多的模块,每个模块对应一个微服务,那么我们在nacos上面则会看到这样的服务列表:

即每个微服务(可以理解为一个运行的jar包)都是对应一条数据,但是Dubbo不一样,就拿我们上面的例子,每个生产者提供的类就是一个对应的服务,很好理解,就是zookeeper里面对应的每个节点,就像这样:

Nacos 版本映射关系
Dubbo | 推荐 Nacos 版本 | Nacos 兼容范围 |
---|---|---|
3.3.0 | 2.3.0 | 2.x |
3.2.21 | 2.1.0 | 2.x |
3.1.11 | 2.0.9 | 2.x |
3.0.10 | 2.0.9 | 2.x |
2.7.21 | 1.x最新版本 | 1.x |
2.6.0 | 1.x最新版本 | 1.x |
作者演示的环境nacos版本是2.2.0,Dubbo版本是3.3.0,JDK是1.8
搭建环境
第一步,搭建最少3个maven模块
作者这边搭建了4个maven模块,他们之间的关系是这样的
注册中心的主要职责是服务的注册与发现,它提供了一个中心化的视图,使得服务消费者能够找到并连接到适当的服务提供者。
- 服务注册:当一个服务启动时,它会将自己的地址(如IP地址和端口号)、版本号等信息注册到注册中心。
- 服务发现:服务消费者在需要调用其他服务时,会向注册中心查询所需服务的地址列表。基于某种策略(例如随机、轮询或根据负载情况),消费者选择一个合适的服务提供者进行直接通信。
- 健康检查:注册中心还负责对已注册的服务进行健康检查。如果某个服务实例不可用了,注册中心会更新其状态,从而避免将请求路由到不健康的实例上。

第二步,编写pom文件
web-server
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.12</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.masiyi</groupId>
<artifactId>web-server</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.masiyi</groupId>
<artifactId>service</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-nacos-spring-boot-starter</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
</project>
server
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.masiyi</groupId>
<artifactId>service</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.12</version>
</dependency>
<dependency>
<groupId>com.masiyi</groupId>
<artifactId>api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
rpc-server
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.12</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.masiyi</groupId>
<artifactId>rpc-server</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-nacos-spring-boot-starter</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.masiyi</groupId>
<artifactId>api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
api
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.masiyi</groupId>
<artifactId>api</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
第三步,编写生产者和消费者
具体的代码请查看代码仓库 : dubbo-nacos
注意这里使用@EnableDubboConfig,@DubboComponentScan
注解代替了老版本的 EnableDubbo
,使用 @DubboService
代替了老版本的 Service
, @DubboReference
代替了 Reference
第四步,编写配置文件
生产者(rpc-server)
properties
spring.application.name=rpc-server
server.port=8082
dubbo.application.name=rpc-server
dubbo.registry.address=nacos://localhost:8848
dubbo.protocol.name=dubbo
dubbo.protocol.port=20881
消费者(web-server)
properties
spring.application.name=web-server
server.port=8083
dubbo.application.name=web-server
dubbo.registry.address=nacos://localhost:8848
dubbo.protocol.port=20885
第五步,启动消费者和生产者
启动完成之后就可以在nacos看到这些消息了



上面的基本页面是没问题的,我们再来看一下每个服务具体的详情页面:

可以看到,这里面的详情信息就是之前我们在zookeeper里面providers
znode看到的消息是一样的。那么我们也可以调用一下接口看看效果也是没问题的:

至此,我们的Dubbo集成Nacos就完成了,随着我们将Dubbo成功集成到Nacos中,这一过程不仅标志着技术上的里程碑,也象征着Dubbo"回归娘家"的历程。Dubbo最初由阿里巴巴开源,并于2011年作为一款高性能的Java RPC框架公开发布。它迅速成为了构建分布式服务架构的首选之一。
在2017年,Dubbo被捐赠给Apache软件基金会(Apache Software Foundation),并在2019年正式毕业成为Apache顶级项目(Top-Level Project)。这一过程不仅是对Dubbo技术实力的认可,更是对其社区活跃度和开放性的一种肯定。在Apache基金会的支持下,Dubbo得到了全球范围内更多的开发者和企业的关注与贡献,进一步推动了其发展和创新。
尽管Dubbo曾一度淡出公众视野,但它始终保持着强劲的生命力,这得益于其开放源代码的本质和活跃的社区支持。阿里巴巴重新重视并投入资源继续发展Dubbo,将其视为其云原生战略的关键部分,进一步巩固了Dubbo在现代分布式系统中的地位。
谢谢大家观看。
