Spring Cloud Alibaba Nacos Discovery
Nacos 是一个 Alibaba 开源的、易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
使用 Spring Cloud Alibaba Nacos Discovery,可基于 Spring Cloud 的编程模型快速接入 Nacos 服务注册功能。

1、服务注册/发现: Nacos Discovery

服务发现是微服务架构体系中最关键的组件之一。如果尝试着用手动的方式来给每一个客户端来配置所有服务提供者的服务列表是一件非常困难的事,而且也不利于服务的动态扩缩容。Nacos Discovery 可以将服务自动注册到 Nacos 服务端并且能够动态感知和刷新某个服务实例的服务列表。除此之外,Nacos Discovery 也将服务实例自身的一些元数据信息-例如 host,port, 健康检查URL,主页等内容注册到 Nacos。Nacos 的获取和启动方式可以参考 Nacos 官网。

2、引入 Nacos Discovery 进行服务注册/发现

如果要在项目中使用 Nacos 来实现服务注册/发现,使用 group ID 为 com.alibaba.cloud 和 artifact ID 为 spring-cloud-starter-alibaba-nacos-discovery 的 starter。

  1. <dependency>
  2. <groupId>com.alibaba.cloud</groupId>
  3. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  4. </dependency>

3、一个使用 Nacos Discovery 进行服务注册/发现并调用的例子

Nacos Discovery 适配了 Netflix Ribbon,可以使用 RestTemplate 或 OpenFeign 进行服务的调用。

3.1. Nacos Server 启动

下载编译后压缩包方式

可以从 最新稳定版本 下载 nacos-server-$version.zip 包。
image.png

  1. unzip nacos-server-$version.zip
  2. # 或者
  3. tar -xvf nacos-server-$version.tar.gz
  4. cd nacos/bin

Linux/Unix/Mac启动

启动命令(standalone代表着单机模式运行,非集群模式):

  1. sh startup.sh -m standalone

image.png
如果使用的是ubuntu系统,或者运行脚本报错提示[[符号找不到,可尝试如下运行:

  1. bash startup.sh -m standalone

image.png

Windows启动

启动命令(standalone代表着单机模式运行,非集群模式):

  1. startup.cmd -m standalone

image.png

3.2. Nacos 服务端添加配置

Nacos Server 启动完毕后,访问控制台打印的管理页面的URL,默认的用户名和密码是nacos。
image.png

3.3. Provider 应用

以下步骤展示了如何将一个服务注册到 Nacos。

  • pom.xml的配置。一个完整的 pom.xml 配置如下所示:

pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <groupId>open.source.test</groupId>
  6. <artifactId>nacos-discovery-test</artifactId>
  7. <version>1.0-SNAPSHOT</version>
  8. <name>nacos-discovery-test</name>
  9. <parent>
  10. <groupId>org.springframework.boot</groupId>
  11. <artifactId>spring-boot-starter-parent</artifactId>
  12. <version>${spring.boot.version}</version>
  13. <relativePath/>
  14. </parent>
  15. <properties>
  16. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  17. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  18. <java.version>1.8</java.version>
  19. </properties>
  20. <dependencyManagement>
  21. <dependencies>
  22. <dependency>
  23. <groupId>org.springframework.cloud</groupId>
  24. <artifactId>spring-cloud-dependencies</artifactId>
  25. <version>${spring.cloud.version}</version>
  26. <type>pom</type>
  27. <scope>import</scope>
  28. </dependency>
  29. <dependency>
  30. <groupId>com.alibaba.cloud</groupId>
  31. <artifactId>spring-cloud-alibaba-dependencies</artifactId>
  32. <version>${spring.cloud.alibaba.version}</version>
  33. <type>pom</type>
  34. <scope>import</scope>
  35. </dependency>
  36. </dependencies>
  37. </dependencyManagement>
  38. <dependencies>
  39. <dependency>
  40. <groupId>org.springframework.boot</groupId>
  41. <artifactId>spring-boot-starter-web</artifactId>
  42. </dependency>
  43. <dependency>
  44. <groupId>org.springframework.boot</groupId>
  45. <artifactId>spring-boot-starter-actuator</artifactId>
  46. </dependency>
  47. <dependency>
  48. <groupId>com.alibaba.cloud</groupId>
  49. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  50. </dependency>
  51. </dependencies>
  52. <build>
  53. <plugins>
  54. <plugin>
  55. <groupId>org.springframework.boot</groupId>
  56. <artifactId>spring-boot-maven-plugin</artifactId>
  57. </plugin>
  58. </plugins>
  59. </build>
  60. </project>
  • application.properties 配置。一些关于 Nacos 基本的配置也必须在 application.properties(也可以是application.yaml)配置,如下所示:

application.properties

  1. server.port=8081
  2. spring.application.name=nacos-provider
  3. spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
  4. management.endpoints.web.exposure.include=*

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

  • 启动 Provider 示例。如下所示:
    1. @SpringBootApplication
    2. @EnableDiscoveryClient
    3. public class NacosProviderDemoApplication {
    4. public static void main(String[] args) {
    5. SpringApplication.run(NacosProviderDemoApplication.class, args);
    6. }
    7. @RestController
    8. public class EchoController {
    9. @GetMapping(value = "/echo/{string}")
    10. public String echo(@PathVariable String string) {
    11. return "Hello Nacos Discovery " + string;
    12. }
    13. }
    14. }
    这个时候就可以在 Nacos的控制台上看到注册上来的服务信息了。

    3.4. Consumer 应用

    Consumer 应用可能还没像启动一个 Provider 应用那么简单。因为在 Consumer 端需要去调用 Provider 端提供的REST 服务。例子中使用最原始的一种方式, 即显示的使用 LoadBalanceClient 和 RestTemplate 结合的方式来访问。pom.xml 和 application.properties 的配置可以参考 1.2 小结。启动一个 Consumer应用的示例代码如下所示:
    通过带有负载均衡的RestTemplate 和 FeignClient 也是可以访问的。
    1. @SpringBootApplication
    2. @EnableDiscoveryClient
    3. public class NacosConsumerApp {
    4. @RestController
    5. public class NacosController{
    6. @Autowired
    7. private LoadBalancerClient loadBalancerClient;
    8. @Autowired
    9. private RestTemplate restTemplate;
    10. @Value("${spring.application.name}")
    11. private String appName;
    12. @GetMapping("/echo/app-name")
    13. public String echoAppName(){
    14. //使用 LoadBalanceClient 和 RestTemplate 结合的方式来访问
    15. ServiceInstance serviceInstance = loadBalancerClient.choose("nacos-provider");
    16. String url = String.format("http://%s:%s/echo/%s",serviceInstance.getHost(),serviceInstance.getPort(),appName);
    17. System.out.println("request url:"+url);
    18. return restTemplate.getForObject(url,String.class);
    19. }
    20. }
    21. //实例化 RestTemplate 实例
    22. @Bean
    23. public RestTemplate restTemplate(){
    24. return new RestTemplate();
    25. }
    26. public static void main(String[] args) {
    27. SpringApplication.run(NacosConsumerApp.class,args);
    28. }
    29. }
    这个例子中注入了一个 LoadBalancerClient 的实例,并且手动的实例化一个 RestTemplate,同时将 spring.application.name 的配置值 注入到应用中来, 目的是调用 Provider 提供的服务时,希望将当前配置的应用名给显示出来。 :::info 在启动 Consumer 应用之前请先将 Nacos 服务启动好。具体启动方式可参考 Nacos 官网。 ::: 启动后,访问 Consumer 提供出来的 http://ip:port/echo/app-name 接口。这里测试启动的 port是 8082。访问结果如下所示:
    访问地址:http://127.0.0.1:8082/echo/app-name
    访问结果:Hello Nacos Discovery nacos-consumer

    4、Nacos Discovery 对外暴露的 Endpoint

    Nacos Discovery 内部提供了一个 Endpoint, 对应的 endpoint id 为 nacos-discovery
    Endpoint 暴露的 json 中包含了两种属性:
  1. subscribe: 显示了当前服务有哪些服务订阅者
  2. NacosDiscoveryProperties: 当前应用 Nacos 的基础配置信息

这是 Endpoint 暴露的 json 示例:

  1. {
  2. "subscribe": [
  3. {
  4. "jsonFromServer": "",
  5. "name": "nacos-provider",
  6. "clusters": "",
  7. "cacheMillis": 10000,
  8. "hosts": [
  9. {
  10. "instanceId": "30.5.124.156#8081#DEFAULT#nacos-provider",
  11. "ip": "30.5.124.156",
  12. "port": 8081,
  13. "weight": 1.0,
  14. "healthy": true,
  15. "enabled": true,
  16. "cluster": {
  17. "serviceName": null,
  18. "name": null,
  19. "healthChecker": {
  20. "type": "TCP"
  21. },
  22. "defaultPort": 80,
  23. "defaultCheckPort": 80,
  24. "useIPPort4Check": true,
  25. "metadata": {
  26. }
  27. },
  28. "service": null,
  29. "metadata": {
  30. }
  31. }
  32. ],
  33. "lastRefTime": 1541755293119,
  34. "checksum": "e5a699c9201f5328241c178e804657e11541755293119",
  35. "allIPs": false,
  36. "key": "nacos-provider",
  37. "valid": true
  38. }
  39. ],
  40. "NacosDiscoveryProperties": {
  41. "serverAddr": "127.0.0.1:8848",
  42. "endpoint": "",
  43. "namespace": "",
  44. "logName": "",
  45. "service": "nacos-provider",
  46. "weight": 1.0,
  47. "clusterName": "DEFAULT",
  48. "metadata": {
  49. },
  50. "registerEnabled": true,
  51. "ip": "30.5.124.201",
  52. "networkInterface": "",
  53. "port": 8082,
  54. "secure": false,
  55. "accessKey": "",
  56. "secretKey": ""
  57. }
  58. }

5、关于 Nacos Discovery Starter 更多的配置项信息

更多关于 Nacos Discovery Starter 的配置项如下所示:

配置项 Key 默认值 说明
服务端地址 spring.cloud.nacos.discovery.server-addr Nacos Server 启动监听的ip地址和端口
服务名 spring.cloud.nacos.discovery.service ${spring.application.name} 注册的服务名
权重 spring.cloud.nacos.discovery.weight 1 取值范围 1 到 100,数值越大,权重越大
网卡名 spring.cloud.nacos.discovery.network-interface 当IP未配置时,注册的IP为此网卡所对应的IP地址,如果此项也未配置,则默认取第一块网卡的地址
注册的IP地址 spring.cloud.nacos.discovery.ip 优先级最高
注册的端口 spring.cloud.nacos.discovery.port -1 默认情况下不用配置,会自动探测
命名空间 spring.cloud.nacos.discovery.namespace 常用场景之一是不同环境的注册的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等
AccessKey spring.cloud.nacos.discovery.access-key 当要上阿里云时,阿里云上面的一个云账号名
SecretKey spring.cloud.nacos.discovery.secret-key 当要上阿里云时,阿里云上面的一个云账号密码
Metadata spring.cloud.nacos.discovery.metadata 使用Map格式配置,用户可以根据自己的需要自定义一些和服务相关的元数据信息
日志文件名 spring.cloud.nacos.discovery.log-name
集群 spring.cloud.nacos.discovery.cluster-name DEFAULT Nacos集群名称
接入点 spring.cloud.nacos.discovery.endpoint 地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
是否集成Ribbon ribbon.nacos.enabled true 一般都设置成true即可
是否开启Nacos Watch spring.cloud.nacos.discovery.watch.enabled true 可以设置成false来关闭 watch