nacos注册中心和配置中心
nacos 一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
nacos官方文档:https://nacos.io/zh-cn/
相关概念:https://nacos.io/zh-cn/docs/architecture.html
nacos是AP架构,注重可用性和分区容错性,java语言,集群架构的话通过nginx做负载均衡,然后节点之间互相同步数据
本文演示在springcloud中使用nacos
版本对应关系
https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E
nacos注册中心
官方基本示例,和属性介绍:https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-discovery
2.3 核心功能
Nacos Discovery
服务注册:Nacos Client会通过发送REST请求的方式向Nacos Server注册自己的服务,提供自身的元数据,比如ip地址、端口等信息。Nacos Server接收到注册请求后,就会把这些元数据信息存储在一个双层的内存Map中。
服务心跳:在服务注册后,Nacos Client会维护一个定时心跳来持续通知Nacos Server,说明服务一直处于可用状态,防止被剔除。默认5s发送一次心跳。
服务同步:Nacos Server集群之间会互相同步服务实例,用来保证服务信息的一致性。 leader raft
服务发现:服务消费者(Nacos Client)在调用服务提供者的服务时,会发送一个REST请求给Nacos Server,获取上面注册的服务清单,并且缓存在Nacos Client本地,同时会在Nacos Client本地开启一个定时任务定时拉取服务端最新的注册表信息更新到本地缓存
服务健康检查:Nacos Server会开启一个定时任务用来检查注册服务实例的健康情况,对于超过15s没有收到客户端心跳的实例会将它的healthy属性置为false(客户端服务发现时不会发现),如果某个实例超过30秒没有收到心跳,直接剔除该实例(被剔除的实例如果恢复发送心跳则会重新注册)
主流的注册中心
CAP C 一致性 A可用性 P 分区容错性
项目依赖
<!--nacos-服务注册发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
配置项
官网 :https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-discovery#%E5%85%B3%E4%BA%8E-nacos-starter-%E6%9B%B4%E5%A4%9A%E7%9A%84%E9%85%8D%E7%BD%AE%E9%A1%B9%E4%BF%A1%E6%81%AF
在spring配置文件中配置项,服务端和客户端大致相同
# 应用名称 (nacos会将该名称当做服务名称) ,
spring.application.name: nacos-producer
spring:
cloud:
nacos:
server-addr: 61.171.5.6:30848 # 需要注意的是客户客户端会在此端口+1000的基础上获取通信端口,具体参考nacos安装中的几个端口
discovery:
# service: service-consumer #注册的服务名称,不配置,默认取spring.application.name
# register-enabled: false #一般会注册成服务提供者和消费者,如果不想成为服务提供者,这里设置false
username: nacos # 服务端没有开启认证,这个也不需要
password: nacos
# group: nacos-producer1 # 默认使用DEFAULT_GROUP作为分组名称
#service: nacos-producer1 # 默认使用spring.application.name作为服务名称
#namespace: public #指定命名空间 ,
# enabled: false # 如果不想使用服务注册和发现,
com.alibaba.cloud.nacos.NacosDiscoveryProperties中你可以找到更多的配置项
producer示例代码
一个用于演示的contrlller,有没有都不会影响客户端的注册
@RestController
@RequestMapping("/product")
public class ProductController {
@Value("${server.port}")
String port;
@RequestMapping("/{id}")
public String get(@PathVariable Integer id) throws InterruptedException {
Thread.sleep(4000);
System.out.println("查询商品"+id);
return "查询商品"+id+":"+port;
}
}
consumer示例代码
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
RestTemplate restTemplate;
// http://localhost:8005/nacos-consumer/order/add
@RequestMapping("/add")
public String add() {
System.out.println("下单成功!");
String msg = restTemplate.getForObject("http://nacos-producer/nacos-producer/123", String.class);
return "Hello World" + msg;
}
}
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder builder){
RestTemplate restTemplate = builder.build();
return restTemplate;
}
}
注意版太新了,这个示例就不好用了,换了旧版本才跑起来,恶心,以下是我失败的版本,都已经不是客户端版本和服务端版本对应不上的问题了
<spring.cloud.alibaba.version>2021.0.4.0</spring.cloud.alibaba.version>
<spring.boot.version>2.6.11</spring.boot.version>
<spring.cloud.version>2021.0.4</spring.cloud.version>
@LoadBalanced 会创建一个LoadBalancerClient的对象,LoadBalancerClient是一个接口,实现是由ribbon或者spring cloud 的 LoadBalancer 来实现,对比了一下依赖,发现2021.0.4这个版本中的nacos-discovery 缺少了默认引入的ribbon依赖,所以以上示例无法运行,添加如下依赖解决
<!--spring cloud 父依赖中已经没有了这个,引入不了,添加版本号单独引入,但是没有了统一的依赖管理-->
<!-- <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
服务的 EndPoint
需要添加配置项
management.endpoints.web.exposure.include=*
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
spring-cloud-starter-alibaba-nacos-discovery 在实现的时候提供了一个EndPoint,EndPoint的访问地址为 http://ip:port/actuator/nacos-discovery
。 EndPoint 的信息主要提供了两类:
1、subscribe: 显示了当前有哪些服务订阅者
2、NacosDiscoveryProperties: 显示了当前服务实例关于 Nacos 的基础配置
一个服务实例访问 EndPoint 的信息如下所示:
{
"subscribe": [
{
"jsonFromServer": "",
"name": "nacos-provider",
"clusters": "",
"cacheMillis": 10000,
"hosts": [
{
"instanceId": "30.5.124.156#8081#DEFAULT#nacos-provider",
"ip": "30.5.124.156",
"port": 8081,
"weight": 1.0,
"healthy": true,
"enabled": true,
"cluster": {
"serviceName": null,
"name": null,
"healthChecker": {
"type": "TCP"
},
"defaultPort": 80,
"defaultCheckPort": 80,
"useIPPort4Check": true,
"metadata": {
}
},
"service": null,
"metadata": {
}
}
],
"lastRefTime": 1541755293119,
"checksum": "e5a699c9201f5328241c178e804657e11541755293119",
"allIPs": false,
"key": "nacos-producer",
"valid": true
}
],
"NacosDiscoveryProperties": {
"serverAddr": "127.0.0.1:8848",
"endpoint": "",
"namespace": "",
"logName": "",
"service": "nacos-provider",
"weight": 1.0,
"clusterName": "DEFAULT",
"metadata": {
},
"registerEnabled": true,
"ip": "30.5.124.201",
"networkInterface": "",
"port": 8082,
"secure": false,
"accessKey": "",
"secretKey": ""
}
}
一份比较完整服务发现的配置展示
未测试,未使用,仅记录
spring:
cloud:
nacos:
discovery:
# Nacos的服务注册地址,可以配置多个,逗号分隔
server-addr: localhost:8848
# 服务注册到Nacos上的名称,一般不用配置
service: coupon-customer-serv
# nacos客户端向服务端发送心跳的时间间隔,时间单位其实是ms
heart-beat-interval: 5000
# 服务端没有接受到客户端心跳请求就将其设为不健康的时间间隔,默认为15s
# 注:推荐值该值为15s即可,如果有的业务线希望服务下线或者出故障时希望尽快被发现,可以适当减少该值
heart-beat-timeout: 20000
# 元数据部分 - 可以自己随便定制
metadata:
mydata: abc
# 客户端在启动时是否读取本地配置项(一个文件)来获取服务列表
# 注:推荐该值为false,若改成true。则客户端会在本地的一个
# 文件中保存服务信息,当下次宕机启动时,会优先读取本地的配置对外提供服务。
naming-load-cache-at-start: false
# 命名空间ID,Nacos通过不同的命名空间来区分不同的环境,进行数据隔离,
namespace: dev
# 创建不同的集群
cluster-name: Cluster-A
# [注意]两个服务如果存在上下游调用关系,必须配置相同的group才能发起访问
group: myGroup
# 向注册中心注册服务,默认为true
# 如果只消费服务,不作为服务提供方,倒是可以设置成false,减少开销
register-enabled: true
nacos配置中心
以下是引入springCloud依赖的用法,单独在springBoot中使用请参考官网
官方文档: https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-config
Nacos 提供用于存储配置和其他元数据的 key/value 存储,为分布式系统中的外部化配置提供服务器端和客户端支持。使用 Spring Cloud Alibaba Nacos Config,您可以在 Nacos Server 集中管理你 Spring Cloud 应用的外部属性配置。
1.维护性 2.时效性 3.安全性
springcloud config 对比
三大优势:
- springcloud config大部分场景结合git 使用, 动态变更还需要依赖Spring Cloud Bus 消息总线来通过所有的客户端变化.
- springcloud config不提供可视化界面
- nacos config使用长轮询更新配置, 一旦配置有变动后,通知Provider的过程非常的迅速, 从速度上秒杀springcloud原来的config几条街,
1.1 快速开始
准备配置,nacos server中新建nacos-config.properties
最佳实践:
Namespace:代表不同环境,如开发、测试、生产环境。
Group:代表某项目,如XX医疗项目、XX电商项目
DataId:每个项目下往往有若干个工程(微服务),每个配置集(DataId)是一个工程(微服务)的主配置文件
权限配置
nacos权限设定,修改修改conf目录下application.properties
nacos.core.auth.enabled=true
只支持命名空间这一级别的权限管理,
1.2 搭建nacos-config服务
通过 Nacos Server 和 spring-cloud-starter-alibaba-nacos-config 实现配置的动态变更
1)引入依赖
<!--Nacos config依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2)添加bootstrap.yml
(就像springboot约定的配置文件是application.properties一样,这个文件会被springCloud进行加载,格式可以是yml和properties格式)
spring:
cloud:
nacos:
server-addr: 61.171.5.6:30848
username: nacos
password: nacos
3)启动服务,测试微服务是否使用配置中心的配置
@SpringBootApplication
@Slf4j
public class NacosConfigApplication {
public static void main(String[] args) throws InterruptedException {
ConfigurableApplicationContext applicationContext = SpringApplication.run(NacosConfigApplication.class, args);
while (true) {
String userName = applicationContext.getEnvironment().getProperty("user.name");
String userAge = applicationContext.getEnvironment().getProperty("user.age");
String config = applicationContext.getEnvironment().getProperty("user.config");
System.err.println("user name :" + userName + "; age: " + userAge+";config:"+config);
TimeUnit.SECONDS.sleep(1);
}
}
}
报错:
1、
org.springframework.cloud.commons.ConfigDataMissingEnvironmentPostProcessor$ImportException: No spring.config.import set
Spring Cloud 新版本默认将 Bootstrap 禁用,需要将 spring-cloud-starter-bootstrap 依赖引入到工程中:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
无语了,禁用了,还不让放在application.properties里面
配置优先级别
多份配置文件中可能有重复配置,优先级别高的配置生效,
在 Nacos Spring Cloud 中,dataId
的完整格式如下:
${prefix}-${spring.profiles.active}.${file-extension}
prefix
默认为spring.application.name
的值,也可以通过配置项spring.cloud.nacos.config.prefix
来配置。spring.profiles.active
即为当前环境对应的 profile,详情可以参考 Spring Boot文档。 注意:当spring.profiles.active
为空时,对应的连接符-
也将不存在,dataId 的拼接格式变成${prefix}.${file-extension}
file-exetension
为配置内容的数据格式,可以通过配置项spring.cloud.nacos.config.file-extension
来配置。目前只支持properties
和yaml
类型。
一份比较完整的测试优先级的配置
spring.application.name: nacos-config
# 会自动根据服务名拉取dataid对应的配置文件。 如果dataid跟服务名不一致 就需要手动指定dataid
# 跟服务名相同的dataid的配置文件,称之为默认的配置文件
# 除了默认的配置文件 ,其他配置文件必须写上后缀
spring:
cloud:
nacos:
server-addr: 61.171.5.6:30848
username: nacos
password: nacos
# 解决控制台循环打印ClientWorker日志
# config:
# namespace: public
# Nacos客户端 默认是Properties的文件扩展名 (只针对默认配置文件和profile)
# 一旦修改成了非Properties格式,则必须通过file-extension进行设置
config:
file-extension: properties
#refresh-enabled: false nacos客户端将无法感知配置的变化
# namespace: public # public默认的命名空间,可以注释掉,加上了似乎有在控制台循环打印ClientWorker日志的问题,我这个版本似乎没这个问题,不过加上了之后会有配置无法读取的问题,所以如果是默认的命名空间还是注释吧
group: DEFAULT_GROUP
shared-configs:
- data-id: cn.sry1201.common.yaml #[0]
refresh: true
group: common_group #默认是Default-group
- data-id: cn.sry1201.common02.yaml #[1]
refresh: true
group: common_group
extension-configs[0]:
data-id: cn.sry1201.share.yaml
refresh: true
group: extension_group
优先级
${prefix}-${spring.profiles.active}.${file-extension}
>${prefix}.${file-extension}
>>extension-configs(下标越大优先级就越大)>shared-configs(下标越大优先级就越大)
1.5 @RefreshScope
@Value注解可以获取到配置中心的值,但是无法动态感知修改后的值,需要利用@RefreshScope注解
@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigController {
@Value("${user.name}")
public String name;
@RequestMapping("/show")
public String show(){
return name;
}
}
nacos整合logback日志
似乎是通过nacos接口获取日志文件,没测试,仅仅进行记录,日志的话,应该也没有动态生效吧
logging:
# 指定日志配置文件位置,指定之后,外部配置文件失效,但是可以被配置文件内部引用,注意logback-spring.xml这个名称不能修改
config: http://(spring.cloud.naoos.config.server-addr)/onfigs?group-DEFAULT_GROUP&tenant-S(spring cloucj&datald-logback-spring.xml
关联信息
- 关联的主题:
- 上一篇:
- 下一篇:
- image: 20221021/1
- 转载自: