进阶指南
本章节展示 spring-cloud-starter-alibaba-nacos-config 和 spring-cloud-starter-alibaba-nacos-discovery 的高级特性和进阶用法。
Nacos 配置中心进阶指南
profile 粒度的配置
spring-cloud-starter-alibaba-nacos-config 在加载服务配置时:
不仅仅加载了以 dataId 为 ${spring.application.name}.${file-extension:properties} 为前缀的基础配置,
还加载了 dataId 为 ${spring.application.name}-${profile}.${file-extension:properties} 的基础配置。
在日常开发中如果遇到多套环境下的不同配置,可以通过 Spring 提供的 ${spring.profiles.active} 这个配置项选择不同情况下的配置。
spring.profiles.active=develop
Nacos 上新增一个 dataId 为:nacos-config-develop.yaml 的基础配置,如下所示:
Data ID: nacos-config-develop.yaml
Group: DEFAULT_GROUP
配置格式: YAML
配置内容: current.env: develop-env
启动 Spring Boot 应用测试的代码如下:
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(ProviderApplication.class, args);
while(true) {
String userName = applicationContext.getEnvironment().getProperty("user.name");
String userAge = applicationContext.getEnvironment().getProperty("user.age");
//获取当前部署的环境
String currentEnv = applicationContext.getEnvironment().getProperty("current.env");
System.err.println("in "+currentEnv+" enviroment; "+"user name :" + userName + "; age: " + userAge);
TimeUnit.SECONDS.sleep(1);
}
}
}
控制台输出结果如下:
in develop-env enviroment; user name :nacos-config-yaml-update; age: 68
2018-11-02 15:34:25.013 INFO 33014 --- [ Thread-11] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6f1c29b7: startup date [Fri Nov 02 15:33:57 CST 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@63355449
如果需要切换到生产环境,只需要更改 ${spring.profiles.active} 参数配置即可。如下所示:
spring.profiles.active=product
同时生产环境上 Nacos 需要添加对应 dataId 的基础配置。例如,在生成环境下的 Nacos 添加了 dataId 为:nacos-config-product.yaml 的配置:
Data ID: nacos-config-product.yaml
Group: DEFAULT_GROUP
配置格式: YAML
配置内容: current.env: product-env
启动测试程序,输出结果如下:
in product-env enviroment; user name :nacos-config-yaml-update; age: 68
2018-11-02 15:42:14.628 INFO 33024 --- [Thread-11] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6aa8e115: startup date [Fri Nov 02 15:42:03 CST 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@19bb07ed
Note:
此案例中我们通过
spring.profiles.active=<profilename>
的方式写死在配置文件中,而在真正的项目实施过程中这个变量的值是需要不同环境而有不同的值。这个时候通常的做法是通过-Dspring.profiles.active=<profile>
参数指定其配置来达到环境间灵活的切换。
自定义 Namespace 的配置
Nacos 内部有 Namespace 的概念:
用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离, 例如开发测试环境和生产环境的资源(如配置、服务)隔离等。 在没有明确指定 ${spring.cloud.nacos.config.namespace} 配置的情况下, 默认使用的是 Nacos 中 public 命名空间即默认的命名空间。如果需要使用自定义的命名空间,可以通过以下配置来实现:
spring.cloud.nacos.config.namespace=YOUR_NAMESPACE_ID
NOTE:
该配置必须放在 bootstrap.properties 文件中。此外 spring.cloud.nacos.config.namespace 的值是 namespace 对应的 id,id 值可以在 Nacos 的控制台获取。并且在添加配置时注意不要选择其他的 namespace,否则将会导致读取不到正确的配置。
自定义 Group 的配置
在没有明确指定 ${spring.cloud.nacos.config.group} 配置的情况下, 默认使用的是组 DEFAULT_GROUP 。如果需要自定义 Group,可以通过以下配置来实现:
spring.cloud.nacos.config.group=YOUR_GROUP_NAME
NOTE:
该配置必须放在 bootstrap.properties 文件中。并且在添加配置时 Group 的值一定要和 spring.cloud.nacos.config.group 的配置值一致。
自定义扩展的 Data Id 配置
Spring Cloud Alibaba Nacos Config 从 0.2.1 版本后,可支持自定义 Data Id 的配置。关于这部分详细的设计可参考这里。 一个完整的配置案例如下所示:
spring.application.name=opensource-service-provider
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
# config external configuration
# 1、Data Id 在默认的组 DEFAULT_GROUP,不支持配置的动态刷新
spring.cloud.nacos.config.extension-configs[0].data-id=ext-config-common01.properties
# 2、Data Id 不在默认的组,不支持动态刷新
spring.cloud.nacos.config.extension-configs[1].data-id=ext-config-common02.properties
spring.cloud.nacos.config.extension-configs[1].group=GLOBALE_GROUP
# 3、Data Id 既不在默认的组,也支持动态刷新
spring.cloud.nacos.config.extension-configs[2].data-id=ext-config-common03.properties
spring.cloud.nacos.config.extension-configs[2].group=REFRESH_GROUP
spring.cloud.nacos.config.extension-configs[2].refresh=true
可以看到:
通过 spring.cloud.nacos.config.extension-configs[n].data-id 的配置方式来支持多个 Data Id 的配置。
通过 spring.cloud.nacos.config.extension-configs[n].group 的配置方式自定义 Data Id 所在的组,不明确配置的话,默认是 DEFAULT_GROUP。
通过 spring.cloud.nacos.config.extension-configs[n].refresh 的配置方式来控制该 Data Id 在配置变更时,是否支持应用中可动态刷新, 感知到最新的配置值。默认是不支持的。
Note:
多个 Data Id 同时配置时,他的优先级关系是 spring.cloud.nacos.config.extension-configs[n].data-id 其中 n 的值越大,优先级越高。
spring.cloud.nacos.config.extension-configs[n].data-id 的值必须带文件扩展名,文件扩展名既可支持 properties,又可以支持 yaml/yml。 此时 spring.cloud.nacos.config.file-extension 的配置对自定义扩展配置的 Data Id 文件扩展名没有影响。
通过自定义扩展的 Data Id 配置,既可以解决多个应用间配置共享的问题,又可以支持一个应用有多个配置文件。
为了更加清晰的在多个应用间配置共享的 Data Id ,你可以通过以下的方式来配置:
# 配置支持共享的 Data Id
spring.cloud.nacos.config.shared-configs[0].data-id=common.yaml
# 配置 Data Id 所在分组,缺省默认 DEFAULT_GROUP
spring.cloud.nacos.config.shared-configs[0].group=GROUP_APP1
# 配置Data Id 在配置变更时,是否动态刷新,缺省默认 false
spring.cloud.nacos.config.shared-configs[0].refresh=true
可以看到:
通过 spring.cloud.nacos.config.shared-configs[n].data-id 来支持多个共享 Data Id 的配置。
通过 spring.cloud.nacos.config.shared-configs[n].group 来配置自定义 Data Id 所在的组,不明确配置的话,默认是 DEFAULT_GROUP。
通过 spring.cloud.nacos.config.shared-configs[n].refresh 来控制该 Data Id 在配置变更时,是否支持应用中动态刷新,默认 false。
配置的优先级
Nacos Config 目前提供了三种配置能力从 Nacos 拉取相关的配置:
A: 通过 spring.cloud.nacos.config.shared-dataids 支持多个共享 Data Id 的配置
B: 通过 spring.cloud.nacos.config.ext-config[n].data-id 的方式支持多个扩展 Data Id 的配置
C: 通过内部相关规则(应用名、应用名+ Profile )自动生成相关的 Data Id 配置
当三种方式共同使用时,他们的一个优先级关系是: A < B < C
配置项参考
更多关于 spring-cloud-starter-alibaba-nacos-config 的 starter 配置项如下所示:
配置项 | key | 默认值 | 说明 |
---|---|---|---|
服务端地址 | spring.cloud.nacos.config.server-addr | 服务器 ip 和端口 | |
DataId 前缀 | spring.cloud.nacos.config.prefix | ${spring.application.name} | DataId 的前缀,默认值为应用名称 |
Group | spring.cloud.nacos.config.group | DEFAULT_GROUP | |
DataId 后缀及内容文件格式 | spring.cloud.nacos.config.file-extension | properties | DataId 的后缀,同时也是配置内容的文件格式,目前只支持 properties |
配置内容的编码方式 | spring.cloud.nacos.config.encode | UTF-8 | 配置的编码 |
获取配置的超时时间 | spring.cloud.nacos.config.timeout | 3000 | 单位为 ms |
配置的命名空间 | spring.cloud.nacos.config.namespace | 常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源隔离等。 | |
AccessKey | spring.cloud.nacos.config.access-key | ||
SecretKey | spring.cloud.nacos.config.secret-key | ||
相对路径 | spring.cloud.nacos.config.context-path | 服务端 API 的相对路径 | |
接入点 | spring.cloud.nacos.config.endpoint | 地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址 | |
是否开启监听和自动刷新 | spring.cloud.nacos.config.refresh-enabled | true | |
集群服务名 | spring.cloud.nacos.config.cluster-name |
Endpoint 信息
请求 http://127.0.0.1:18083/actuator/nacosconfig 地址,可以看到相关的 EndPoint 节点信息。
$ curl http://127.0.0.1:18084/actuator/nacosconfig
响应结果:
{
"NacosConfigProperties": {
"serverAddr": "127.0.0.1:8848",
"username": "",
"password": "",
"encode": null,
"group": "DEFAULT_GROUP",
"prefix": "PREFIX",
"fileExtension": "properties",
"timeout": 3000,
"maxRetry": null,
"configLongPollTimeout": null,
"configRetryTime": null,
"enableRemoteSyncConfig": false,
"endpoint": null,
"namespace": "NAMESPACE",
"accessKey": null,
"secretKey": null,
"ramRoleName": null,
"contextPath": null,
"clusterName": null,
"name": null,
"sharedConfigs": null,
"extensionConfigs": null,
"refreshEnabled": true,
"configServiceProperties": {
"encode": "",
"secretKey": "",
"serveraddr": "127.0.0.1:8848",
"prefix": "PREFIX",
"configLongPollTimeout": "",
"maxRetry": "",
"password": "",
"configRetryTime": "",
"endpoint": "",
"serverAddr": "127.0.0.1:8848",
"accessKey": "",
"enableRemoteSyncConfig": "false",
"clusterName": "",
"namespace": "NAMESPACE",
"ramRoleName": "",
"username": "",
"group": "DEFAULT_GROUP"
},
"refreshableDataids": null,
"extConfig": null,
"sharedDataids": null
},
"RefreshHistory": [],
"Sources": [
{
"lastSynced": "2023-05-10 09:35:50",
"dataId": "nacos-config-example.properties"
}
]
}
Nacos 服务注册与发现进阶指南
原理
spring-cloud-starter-alibaba-nacos-discovery 遵循了 Spring Cloud Common 标准,实现了 AutoServiceRegistration、ServiceRegistry、Registration 这三个接口。
在 Spring Cloud 应用的启动阶段,监听了 WebServerInitializedEvent 事件,当 Web 容器初始化完成后,即收到 WebServerInitializedEvent 事件后,会触发注册的动作,调用 ServiceRegistry 的 register 方法,将服务注册到 Nacos Server。
IPv4 至 IPv6 地址迁移方案
IPv4 和 IPv6 地址双注册
在配置完成 Spring Cloud Loadbalancer 作为负载均衡策略后,应用启动后会默认将微服务的 IPv4 地址和 IPv6 地址注册到注册中心中,其中 IPv4 地址会存放在 Nacos 服务列表中的 IP 字段下, IPv6 地址在 Nacos 的 metadata 字段中,其对应的 Key 为 IPv6 。当服务消费者调用服务提供者时,会根据自身的 IP 地址栈支持情况,选择合适的 IP 地址类型发起服务调用。
具体规则:
- 服务消费者本身支持 IPv4 和 IPv6 双地址栈或仅支持 IPv6 地址栈的情况下,服务消费者会使用服务提供的 IPv6 地址发起服务调用,IPv6 地址调用失败且服务本身同时支持 IPv4 地址栈时,暂不支持切换到 IPv4 地址发起重试调用;
- 服务消费者本身仅支持 IPv4 单地址栈的情况下,服务消费者会使用服务提供的 IPv4 地址发起服务调用。
仅注册 IPv4
如果您只想使用 IPv4 地址进行注册,可以在 application.properties 使用如下配置项进行配置:
spring.cloud.nacos.discovery.ip-type=IPv4
仅注册 IPv6
如果您只想使用 IPv6 地址,可以在 application.properties 使用如下配置项进行配置:
spring.cloud.nacos.discovery.ip-type=IPv6
配置项参考
更多关于 spring-cloud-starter-alibaba-nacos-discovery 的 starter 配置项如下所示:
配置项 | key | 默认值 | 说明 |
---|---|---|---|
服务端地址 | spring.cloud.nacos.discovery.server-addr | ||
服务名 | spring.cloud.nacos.discovery.service | 应用名 | 注册到 Nacos 上的服务名称,默认值为应用名称 |
权重 | spring.cloud.nacos.discovery.weight | 1 | 取值范围 1 到 100,数值越大,权重越大 |
网卡名 | spring.cloud.nacos.discovery.network-interface | 当 IP 未配置时,注册的 IP 为此网卡所对应的 IP 地址,如果此项也未配置,则默认取第一块网卡的地址 | |
注册的 IP 地址 | spring.cloud.nacos.discovery.ip | 优先级最高 | |
注册的 IP 地址类型 | spring.cloud.nacos.discovery.ip-type | 双栈地址 | 可以配置 IPv4 和 IPv6 两种类型,如果网卡同类型 IP 地址存在多个,希望制定特定网段地址,可使用spring.cloud.inetutils.preferred-networks 配置筛选地址 |
注册的端口 | 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 | 地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址 | |
是否集成 LoadBalancer | spring.cloud.loadbalancer.nacos.enabled | false | |
是否开启 Nacos Watch | spring.cloud.nacos.discovery.watch.enabled | false | 可以设置成 true 来开启 watch |
是否启用 Nacos | spring.cloud.nacos.discovery.register-enabled | true | 默认启动,设置为 false 时会关闭自动向 Nacos 注册的功能 |
Endpoint 信息
请求 http://127.0.0.1:18083/actuator/nacosdiscovery 地址,可以看到相关的 EndPoint 节点信息。
$ curl http://127.0.0.1:18083/actuator/nacosdiscovery
响应结果:
{
"subscribe": [],
"NacosDiscoveryProperties": {
"serverAddr": "127.0.0.1:8848",
"username": "nacos",
"password": "nacos",
"endpoint": "",
"namespace": "",
"watchDelay": 30000,
"logName": "",
"service": "service-consumer",
"weight": 1,
"clusterName": "DEFAULT",
"group": "DEFAULT_GROUP",
"namingLoadCacheAtStart": "false",
"metadata": {
"IPv6": null,
"preserved.register.source": "SPRING_CLOUD"
},
"registerEnabled": true,
"ip": "192.168.3.19",
"networkInterface": "",
"ipType": null,
"port": 18083,
"secure": false,
"accessKey": "",
"secretKey": "",
"heartBeatInterval": null,
"heartBeatTimeout": null,
"ipDeleteTimeout": null,
"instanceEnabled": true,
"ephemeral": true,
"failureToleranceEnabled": false,
"failFast": true,
"nacosProperties": {
"password": "nacos",
"endpoint": "",
"secretKey": "",
"serverAddr": "127.0.0.1:8848",
"accessKey": "",
"clusterName": "DEFAULT",
"namespace": "",
"com.alibaba.nacos.naming.log.filename": "",
"namingLoadCacheAtStart": "false",
"failFast": "true",
"username": "nacos"
}
}
}