Apache Dubbo 微服务注册配置新选择:Nacos

在之前的文章中, 有介绍过利用 Zookeeper + Apollo 作为 Dubbo 的注册中心 + 配置中心 =>Zookeeper&Dubbo&Apollo In Docker, 在之前的场景下, 我们需要部署及维护 Zookeeper + Apollo 这两个中间件, 虽然不是很麻烦, 但是这两个中间件毕竟不是阿里出品, 在未来的发展上, 可能与 Dubbo 的结合不是会很好, 因此在阿里的开源生态中, 由阿里本身又开源了一个中间件 Nacos 一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

Nacos 介绍

Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。

Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。

Nacos 在其 roadmap 上, 我们可以看到未来 Nacos 将很好的为 Dubbo 提供服务治理的愿景。

环境准备

  • Centos 7.5
  • Docker 18.06.1-ce
  • Docker-compose 1.22.0

    前面有介绍 Docker Installation 大家可以参考这篇文章

Nacos 安装

在 [Nacos] 开源生态中, 我们找到了其官方提供的 Dockerfile 项目 nacos-docker

Dokcer Hub 上 我们可以看到其官方镜像的最新版本, 笔者现在看到的是 0.6.0 版本

在其官方项目中, [Nacos] 已经提供了多种启动模式, 所以我们在测试时, 无需做多余修改, 直接按照官方文档进行部署即可

下载其官方 Git 项目

1
2
git clone https://github.com/nacos-group/nacos-docker.git
cd nacos-docker

Stand-alone 启动

1
docker-compose -f example/standalone.yaml up -d

集群模式此处不介绍, 在真正环境配置时, 请使用集群模式

打开 Nacos 控制台

1
http://127.0.0.1:8848/nacos/

Dubbo Nacos 集成

在 Dubbo PPMC mercyblitz 的推动下, 目前 dubbo-registry-nacos(基于 Dubbo 配置中心 SPI 的 Nacos 实现项目)已经 PR 到 Dubbo 组织下, 等待审核发布.

在此基础上, mercyblitz 在自己的技术周报直播里, 分享了一期关于 Dubbo Nacos 集成

因为 mercyblitz 的分享是基于 spring-framework, 所以笔者在基于 dubbo-spirng-boot-starter 上, 写了一个例子, 供大家参考

Maven dependency

1
2
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
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.5</version>
</dependency>

<!-- Dubbo Nacos registry dependency -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
<version>2.6.5-SNAPSHOT</version>
</dependency>

<!-- Spring Context Extras see dubbo-spring-boot-starter readme -->
<dependency>
<groupId>com.alibaba.spring</groupId>
<artifactId>spring-context-support</artifactId>
<version>1.0.2</version>
</dependency>

<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.30.Final</version>
</dependency>

定义 service 接口

1
2
3
4
public interface DemoService {

String sayName(String name);
}

提供 service 实现者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Service(version = "${demo.service.version}")
public class DefaultService implements DemoService {

@Value("${demo.service.name}")
private String serviceName;

@Override
public String sayName(String message) {

RpcContext rpcContext = RpcContext.getContext();
return String.format("Service [name :%s , port : %d] %s(\"%s\") : Hello,%s",
serviceName,
rpcContext.getLocalPort(),
rpcContext.getMethodName(),
message,
message);
}
}

service 提供者配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
## Dubbo Application info
dubbo.application.id=dubbo-provider-demo
dubbo.application.name=dubbo-provider-demo
## Nacos registry address
dubbo.registry.id=my-nacos
dubbo.registry.address=nacos://127.0.0.1:8848
## Dubbo Protocol using random port
dubbo.protocol.name=dubbo
dubbo.protocol.port=-1
# Provider @Service info
demo.service.version=1.0.0
demo.service.name=demoService

dubbo.scan.basePackages = com.sky.dubbo.nacos.demo.service

启动 service 提供者

此注解使用写法仅为测试

1
2
3
4
5
6
7
8
9
10
11
12
13
@EnableAutoConfiguration
public class DubboNacosDemoApplication {

public static void main(String[] args) throws IOException {

Properties prop = new Properties();
URL url = ApplicationRunner.class.getClassLoader().getResource("provider.properties");
prop.load(url.openStream());

new SpringApplicationBuilder(DubboNacosDemoApplication.class)
.web(WebApplicationType.NONE).properties(prop).run(args);
}
}

可开启多个service 提供者, idea 上修改启动配置, 允许并行启动 allow running in parallel, 此处开启了三个服务提供者

service 消费者配置文件

1
2
3
4
5
6
7
8
## Dubbo Application info
dubbo.application.name = dubbo-consumer-demo

## Nacos registry address
dubbo.registry.address = nacos://127.0.0.1:8848

# @Reference version
demo.service.version= 1.0.0

启动 service 消费者

此注解使用写法仅为测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@EnableAutoConfiguration
public class DubboNacosDemoConsumerApplication {
@Reference(version = "${demo.service.version}")
private DemoService demoService;


@PostConstruct
public void init() {
for (int i = 0; i < 10; i++) {
System.out.println(demoService.sayName("Mercy"));
}
}

public static void main(String[] args) throws IOException {
Properties prop = new Properties();
URL url = ApplicationRunner.class.getClassLoader().getResource("consumer.properties");
prop.load(url.openStream());
SpringApplication app = new SpringApplication(DubboNacosDemoConsumerApplication.class);
app.setDefaultProperties(prop);
app.run(args);
}
}

消费者启动打印的输出

1
2
3
4
5
6
7
8
9
10
Service [name :demoService , port : 20881] sayName("Mercy") : Hello,Mercy
Service [name :demoService , port : 20880] sayName("Mercy") : Hello,Mercy
Service [name :demoService , port : 20882] sayName("Mercy") : Hello,Mercy
Service [name :demoService , port : 20881] sayName("Mercy") : Hello,Mercy
Service [name :demoService , port : 20882] sayName("Mercy") : Hello,Mercy
Service [name :demoService , port : 20881] sayName("Mercy") : Hello,Mercy
Service [name :demoService , port : 20880] sayName("Mercy") : Hello,Mercy
Service [name :demoService , port : 20882] sayName("Mercy") : Hello,Mercy
Service [name :demoService , port : 20880] sayName("Mercy") : Hello,Mercy
Service [name :demoService , port : 20882] sayName("Mercy") : Hello,Mercy

常见问题

如果启动时报错 ClassNotFound : com.alibaba.spring.util.PropertySourcesUtils

1
2
3
4
5
Caused by: java.lang.ClassNotFoundException: com.alibaba.spring.util.PropertySourcesUtils
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_161]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_161]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338) ~[na:1.8.0_161]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_161]

请加入 spring-context-support, 可查看dubbo-spirng-boot-starter 官方推荐的依赖

1
2
3
4
5
<dependency>
<groupId>com.alibaba.spring</groupId>
<artifactId>spring-context-support</artifactId>
<version>1.0.2</version>
</dependency>

如果启动时报错 ClassNotFound : io.netty.channel.nio.NioEventLoopGroup

1
2
3
4
5
Caused by: java.lang.ClassNotFoundException: io.netty.channel.nio.NioEventLoopGroup
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_161]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_161]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338) ~[na:1.8.0_161]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_161]

请加入 netty-all

1
2
3
4
5
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.30.Final</version>
</dependency>