自从有了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项目,引入如下依赖:
| 12
 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。
| 12
 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注解。
| 12
 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;
 
 
 
 
 
 @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的依赖,是为了同时演示这两种方式的消费。
| 12
 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.
| 12
 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注解。
| 12
 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;
 
 
 
 
 
 @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注解,否则可以不加。
| 12
 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;
 
 
 
 
 
 @Configuration
 public class RestTemplateConfig {
 
 @Bean
 @LoadBalanced
 public RestTemplate restTemplate() {
 return new RestTemplate();
 }
 }
 
 | 
使用feign方式消费,需要有feign的client,如下,且项目主函数还需引入@EnableFeignClients
注解。
| 12
 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;
 
 
 
 
 
 @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 的信息如下所示:
| 12
 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上了,如下图所示:

服务消费
这里需要先启动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 中的其他配置信息如下图所示:

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