0%

springcloud使用nacos进行服务注册与发现

自从有了spring-cloud-alibaba的开源之后,springcloud中使用nacos进行服务的注册与发现就已变得非常容易,只需要引入“spring-cloud-starter-alibaba-nacos-discovery”即可,然后开启@EnableDiscoveryClient,便可以做到无缝替换eureka和consul等注册中心。

下面通过给出一个简单的案例来演示springcloud中如何使用nacos。

nacos-discovery-stater原理

首先来看一下springcloud中nacos进行服务注册与发现的原理。

服务注册

spring-cloud-starter-alibaba-nacos-discovery遵循了spring-cloud-common标准,实现了 AutoServiceRegistration、ServiceRegistry、Registration 这三个接口。

在springcloud应用的启动阶段,监听了WebServerInitializedEvent事件,当Web容器初始化完成后,即收到WebServerInitializedEvent 事件后,会触发注册的动作,调用ServiceRegistry的register方法,将服务注册到 Nacos Server。

服务发现

NacosServerList 实现了 com.netflix.loadbalancer.ServerList 接口,并在 @ConditionOnMissingBean 的条件下进行自动注入,默认集成了Ribbon。

如果需要有更加自定义的可以使用 @Autowired 注入一个 NacosRegistration 实例,通过其持有的 NamingService 字段内容直接调用 Nacos API。

nacos-service-provider

创建一个服务提供者的springcloud项目,引入如下依赖:

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
<properties>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
<spring-cloud.alibaba.version>0.2.1.RELEASE</spring-cloud.alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>

在项目的application.yml文件中配置nacos相关的配置信息如下:

如果不想使用 Nacos 作为您的服务注册与发现,可以将 spring.cloud.nacos.discovery 设置为 false。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
spring:
application:
name: nacos-service-provider
cloud:
nacos:
discovery:
register-enabled: true
server-addr: 127.0.0.1:8848
weight: 1
namespace: dev
management:
endpoints:
web:
exposure:
include: "*"

server:
port: 8080

接着便是创建一个服务,供调用者使用,勿忘在主函数引入@EnableDiscoveryClient注解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.lazycece.scac.nacos.discovery.provider.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* @author lazycece
* @date 2019/03/19
*/
@RestController
@RequestMapping("/nacos")
public class NacosProviderController {
@GetMapping("/provider/{name}")
public String provider(@PathVariable String name) {
return "hello," + name;
}
}

nacos-service-consumer

创建一个服务消费者的springcloud项目,引入如下依赖,这里多引入了open-feign和ribbon的依赖,是为了同时演示这两种方式的消费。

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
37
38
39
40
41
42
43
44
45
<properties>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
<spring-cloud.alibaba.version>0.2.1.RELEASE</spring-cloud.alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>

在项目的application.yml文件中配置nacos相关的配置信息如下:

如果不想使用 Nacos 作为您的服务注册与发现,可以将 spring.cloud.nacos.discovery 设置为 false.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
spring:
application:
name: nacos-service-consumer
cloud:
nacos:
discovery:
register-enabled: true
server-addr: 127.0.0.1:8848
weight: 1
namespace: dev
management:
endpoints:
web:
exposure:
include: "*"

server:
port: 8081

创建服务消费者的代码如下,勿忘在主函数引入@EnableDiscoveryClient注解。

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.lazycece.scac.nacos.discovery.consumer.controller;

import com.lazycece.scac.nacos.discovery.consumer.api.FeignConsumerApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
* @author lazycece
* @date 2019/03/19
*/
@RestController
@RequestMapping("/nacos/consumer")
public class NacosConsumerController {

private LoadBalancerClient loadBalancerClient;
private RestTemplate restTemplate;
private FeignConsumerApi feignConsumerApi;

@Autowired
public NacosConsumerController(LoadBalancerClient loadBalancerClient, RestTemplate restTemplate,
FeignConsumerApi feignConsumerApi) {
this.loadBalancerClient = loadBalancerClient;
this.restTemplate = restTemplate;
this.feignConsumerApi = feignConsumerApi;
}

@GetMapping("/rest/{name}")
public String rest(@PathVariable String name) {
ServiceInstance serviceInstance = loadBalancerClient.choose("nacos-service-provider");
String url = String.format("http://%s:%s/nacos/provider/%s",
serviceInstance.getHost(), serviceInstance.getPort(), name);
System.out.println("url -> " + url);
return restTemplate.getForObject(url, String.class);
}

@GetMapping("/feign/{name}")
public String feign(@PathVariable String name) {
return feignConsumerApi.provider(name);
}


@GetMapping("/ribbon/{name}")
public String ribbon(@PathVariable String name) {
return restTemplate.getForObject("http://nacos-service-provider/nacos/provider/" +
name, String.class);
}
}

要使用rest方式消费,需要注入RestTemplate,如果需要用ribbon来进行负载均衡,则可以@LoadBalanced注解,否则可以不加。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.lazycece.scac.nacos.discovery.consumer.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
* @author lazycece
* @date 2019/03/19
*/
@Configuration
public class RestTemplateConfig {

@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

使用feign方式消费,需要有feign的client,如下,且项目主函数还需引入@EnableFeignClients
注解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.lazycece.scac.nacos.discovery.consumer.api;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

/**
* @author lazycece
* @date 2019/03/19
*/
@FeignClient("nacos-service-provider")
@RequestMapping("/nacos")
public interface FeignConsumerApi {

@GetMapping("/provider/{name}")
String provider(@PathVariable String name);
}

服务注册与发现案例验证

需要先启动nacos-server服务,安装部署详见 nacos安装部署

服务的 EndPoint

spring-cloud-starter-alibaba-nacos-discovery 在实现的时候提供了一个EndPoint,EndPoint的访问地址为 http://ip:port/actuator/nacos-discovery 。因为我们加了 spring-boot-starter-actuator 依赖,所以可以查看endpoint信息。EndPoint 的信息主要提供了两类:

  • subscribe: 显示了当前有哪些服务订阅者
  • NacosDiscoveryProperties: 显示了当前服务实例关于 Nacos 的基础配置

其中一个服务实例访问 EndPoint 的信息如下所示:

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
{
"subscribe":[

],
"NacosDiscoveryProperties":{
"serverAddr":"127.0.0.1:8848",
"endpoint":"",
"namespace":"dev",
"logName":"",
"service":"nacos-service-provider",
"weight":1,
"clusterName":"DEFAULT",
"namingLoadCacheAtStart":"false",
"metadata":{

},
"registerEnabled":true,
"ip":"192.168.3.8",
"networkInterface":"",
"port":8080,
"secure":false,
"accessKey":"",
"secretKey":""
}
}

nacos管界面

访问 http://localhost:8848/nacos/ 进入nacos的管理界面,查看 服务管理->服务列表 模块,便可以看到我们的服务消费者和提供者已经注册到nacos上了,如下图所示:

springcloud-nacos-2

服务消费

这里需要先启动nacos服务,然后启动上面两个服务,访问如下地址:
http://localhost:8081/nacos/consumer/rest/lazycece
http://localhost:8081/nacos/consumer/ribbon/lazycece
http://localhost:8081/nacos/consumer/feign/lazycece

输出信息:hello,lazycece

更多springcloud nacos信息

关于 spring-cloud-starter-alibaba-nacos-discovery 中的其他配置信息如下图所示:

springcloud-nacos-1

案例源码

案例源码地址:
https://github.com/lazycece/springcloud-actual-combat/tree/master/springcloud-ac-alibaba/springcloud-ac-alibaba-nacos-discovery