文章目录
- 一、什么是Nacos
- 1.1、Nacos的由来
- 1.2、Nacos的特性
- 1.3、Nacos的下载和启动
- 二、Nacos服务注册
- 2.1、代码示例
- 2.2、各种注册中心的比较
- CAP定理
- 多个注册中心比较
- 三、Nacos配置中心
- 3.1、Nacos配置管理
- 3.2、代码示例
- 3.3、多环境多项目管理
- 3.3.1、命名空间
- 3.3.2、Group分组
- 3.3.3、DataId
一、什么是Nacos
1.1、Nacos的由来
Nacos 是Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
Nacos = Eureka+Config +Bus,替代Eureka做服务注册中心,替代Config做服务配置中心。
1.2、Nacos的特性
Nacos的特性,官网解释如下:
- 服务发现和服务健康监测
Nacos 支持基于 DNS 和基于 RPC 的服务发现。服务提供者使用 原生SDK、OpenAPI、或一个独立的Agent TODO注册 Service 后,服务消费者可以使用DNS TODO 或HTTP&API查找和发现服务。
Nacos 提供对服务的实时的健康检查,阻止向不健康的主机或服务实例发送请求。Nacos 支持传输层 (PING 或 TCP)和应用层 (如HTTP、MySQL、用户自定义)的健康检查。 对于复杂的云环境和网络拓扑环境中(如 VPC、边缘网络等)服务的健康检查,Nacos 提供了agent 上报模式和服务端主动检测2种健康检查模式。Nacos 还提供了统一的健康检查仪表盘,帮助您根据健康状态管理服务的可用性及流量。
- 动态配置服务
动态配置服务可以让您以中心化、外部化和动态化的方式管理所有环境的应用配置和服务配置。动态配置消除了配置变更时重新部署应用和服务的需要,让配置管理变得更加高效和敏捷。配置中心化管理让实现无状态服务变得更简单,让服务按需弹性扩展变得更容易。
Nacos 提供了一个简洁易用的UI (控制台样例 Demo) 帮助您管理所有的服务和应用的配置。Nacos还提供包括配置版本跟踪、金丝雀发布、一键回滚配置以及客户端配置更新状态跟踪在内的一系列开箱即用的配置管理特性,帮助您更安全地在生产环境中管理配置变更和降低配置变更带来的风险。
- 动态 DNS 服务
动态 DNS 服务支持权重路由,让您更容易地实现中间层负载均衡、更灵活的路由策略、流量控制以及数据中心内网的简单DNS解析服务。动态DNS服务还能让您更容易地实现以 DNS 协议为基础的服务发现,以帮助您消除耦合到厂商私有服务发现 API 上的风险。Nacos 提供了一些简单的 DNS APIs TODO 帮助您管理服务的关联域名和可用的 IP:PORT 列表.
- 服务及其元数据管理
Nacos 能让您从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略、服务的 SLA 以及最首要的 metrics 统计数据。
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
1.3、Nacos的下载和启动
Nacos的官方下载地址为点击跳转至官方下载地址,根据自己需要,可下载linux和windows版本;并且要根据Springboot+Spring Cloud+Spring Cloud Alibaba的版本,合理选择nacos版本。
我下载linux 2.1.1版本,部署在阿里云服务器,解压到文件夹下,
使用启动命令:sh bin/startup.sh -m standalone
,开启Nacos;
访问http://182.92.122.196:8848/nacos/index.htm,出现登录页面,nacos服务注册中心启动成功。
避坑小妙招:
nacos客户端升级到2.1版本后,新增了gRPC的通信方式,新增了两个偏移量端口(9848,9849)在原端口(8848)基础上面偏移量1000和1001。
端口8848:服务使用。
偏移量端口--9848: 客户端gRPC请求服务端端口,用于客户端向服务端发起连接和请求。
便宜连端口--9849: 服务端gRPC请求服务端端口,用于服务间同步等。
云服务器上要开通相应的服务端口:8848,9848,9849。
二、Nacos服务注册
2.1、代码示例
第一步,建立两个生产者,注册进入Nacos列表,
在父工程pom文件,增加依赖管理
<!--spring cloud alibaba 2.2.0.RELEASE-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
新建Model:cloud-alibaba-provider-payment6001,pom文件添加依赖:
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringBoot整合Web组件 -->
<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>
<!--日常通用jar包配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
增加配置文件,application.yml,要时刻注意缩进,Nacos启动正常,控制台报如下错误的时候,就要去看看配置是不是出了问题,不要犯同样的错误!
server:
port: 6001
spring:
application:
name: nacos-provider-payment
cloud:
nacos:
discovery:
server-addr: 182.92.122.196:8848
management:
endpoints:
web:
exposure:
include: '*'
启动类添加注解@EnableDiscoveryClient,用于服务发现
/**
* @Auther: songweichao
* @Date: 2023-05-10 16:52
* @Description:
*/
@EnableDiscoveryClient
@SpringBootApplication
public class PaymentMain6001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain6001.class,args);
}
}
业务类编写,方便调用,
/**
* @Auther: songweichao
* @Date: 2023-05-10 16:59
* @Description:
*/
@RestController
@RequestMapping("/payment")
public class PaymentController {
@Value("${server.port}")
private String port;
@GetMapping(value="/showPort/{id}")
public String getPayment(@PathVariable("id") String id){
return "生产者报道,Port:"+port+"\t id:"+id;
}
}
第二步,再建立一个cloud-alibaba-provider-payment6001,步骤同上。
第三步,新建cloud-alibaba-consumer-nacos-order,作为消费者,pom依赖同生产者,配置application.yml,其中service-url.nacos-payment-service参数表示消费者将要去访问的微服务名称。
server:
port: 83
spring:
application:
name: nacos-consumer-order
cloud:
nacos:
discovery:
server-addr: 182.92.122.196:8848
service-url:
nacos-payment-service: http://nacos-provider-payment
启动类添加注解@EnableDiscoveryClient
/**
* @Auther: songweichao
* @Date: 2023-05-11 10:22
* @Description:
*/
@EnableDiscoveryClient
@SpringBootApplication
public class OrderNacosMain83 {
public static void main(String[] args) {
SpringApplication.run(OrderNacosMain83.class,args);
}
}
添加配置类ApplicationConfig,使用RestTemplate实现远程调用。
@Configuration
public class ApplicationConfig
{
@Bean
@LoadBalanced
public RestTemplate getRestTemplate()
{
return new RestTemplate();
}
}
业务类调用
@RestController
public class OrderNacosController {
@Resource
private RestTemplate restTemplate;
@Value("${service-url.nacos-payment-service}")
private String serviceURL;
@GetMapping("/consumer/payment/nacos/{id}")
public String getSome(@PathVariable("id")String id){
return restTemplate.getForObject(serviceURL+"/payment/showPort/"+id,String.class);
}
}
分别启动6001、6002、83项目,查看Nacos服务列表,注册成功。
测试访问http://localhost:83/consumer/payment/nacos/12346,结果成功
通过测试,看到Nacos支持负载均衡,这是因为Nacos中集成了ribbon。
2.2、各种注册中心的比较
常见的注册中心有Zookeeper、Eureka、Nacos、Consul;比较他们之间的不同,需要参考CAP定理。
CAP定理
CAP定理,指的是在分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可同时获得。
其中:
- 一致性(C):所有节点都可以访问到最新的数据。
- 可用性(A):每个请求都是可以得到响应的,不管请求是成功还是失败。
- 分区容错性(P):除了全部整体网络故障,其他故障都不能导致整个系统不可用。
在分布式存储系统中,最多只能实现上面的两点。分区容错性由于当前的网络肯定会出现延迟丢包等问题是必须需要实现的。所以只能在一致性和可用性之间进行权衡。
- CP: 如果不要求A(可用),每个请求都需要在服务器之间保持强一致,而P(分区)会导致同步时间无限延长(也就是等待数据同步完才能正常访问服务),一旦发生网络故障或者消息丢失等情况,就要牺牲用户的体验,等待所有数据全部一致了之后再让用户访问系统。
- AP:要高可用并允许分区,则需放弃一致性。一旦分区发生,节点之间可能会失去联系,为了高可用,每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。
多个注册中心比较
C是所有节点在同一时间看到的数据是一致的;而A的定义是所有的请求都会收到响应。
Nacos 支持AP和CP模式的切换,何时选择使用何种模式?
一般来说,如果不需要存储服务级别的信息且服务实例是通过nacos-client注册,并能够保持心跳上报,那么就可以选择AP模式。当前主流的服务如 Spring cloud 和 Dubbo 服务,都适用于AP模式,AP模式为了服务的可能性而减弱了一致性,因此AP模式下只支持注册临时实例。
如果需要在服务级别编辑或者存储配置信息,那么 CP 是必须,K8S服务和DNS服务则适用于CP模式。CP模式下则支持注册持久化实例,此时则是以 Raft 协议为集群运行模式,该模式下注册实例之前必须先注册服务,如果服务不存在,则会返回错误。
切换方式:
curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'
三、Nacos配置中心
Nacos除了服务注册的功能,还可以作为配置中心,提供配置给微服务。
3.1、Nacos配置管理
在上图配置列表,新增配置文件:
其中 Data ID的格式如下:
${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 的拼接格式变成 p r e f i x . {prefix}. prefix.{file-extension}
- file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 和 yaml 类型。
3.2、代码示例
新建cloud-alibaba-config-nacos-client,调用Nacos 配置中心的配置,pom文件添加依赖
<!--nacos-config-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--nacos-discovery-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--web + actuator-->
<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.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
增加bootstrap.yml和application.yml,springboot中配置文件的加载是存在优先级顺序的,bootstrap优先级高于application
bootstrap:
server:
port: 6088
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: 182.92.122.196:8848
config:
server-addr: 182.92.122.196:8848
file-extension: yaml
application:
spring:
profiles:
active: dev
配置 应用要到Nacos 找nacos-config-client-dev.yml文件
启动类
/**
* @Auther: songweichao
* @Date: 2023-05-11 13:01
* @Description:
*/
@EnableDiscoveryClient
@SpringBootApplication
public class NacosConfigClientMain6088 {
public static void main(String[] args) {
SpringApplication.run(NacosConfigClientMain6088.class,args);
}
}
业务类测试
@RefreshScope:在控制器类加入@RefreshScope注解,使当前类下的配置支持Nacos的动态刷新功能。
@RestController
@RefreshScope
public class ConfigClientController {
@Value("${config.info}")
private String configInfo;
@GetMapping("/config/info")
public String getInfo(){
return configInfo;
}
}
访问http://localhost:6088/config/info,成功获取config.info,且在Nacos配置上修改后,客户端能及时刷新,获取最新配置。
3.3、多环境多项目管理
项目开发中,同一个微服务面对开发环境、测试环境、生产环境,要在不同的阶段指定不同的配置;不同的服务也有同样的需求,Nacos如何区分,做到井井有条呢?这里用到了三种方案
3.3.1、命名空间
增加命名空间,自动生成空间ID
配置文件中,增加namespace,配置空间ID
server:
port: 6088
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: 182.92.122.196:8848
config:
server-addr: 182.92.122.196:8848
file-extension: yaml
namespace: f4f26a88-a7c7-4182-a20d-6fce7610d532
这时候,项目启动加载配置,就找空间ID为f4f26a88-a7c7-4182-a20d-6fce7610d532下面的nacos-config-client-dev.yaml文件中的信息,而不是原来的默认空间。
3.3.2、Group分组
同一个命名空间下,也可以设置不同的分组,实现环境区分
在config下增加一条group的配置即可。可配置为DEFAULT_GROUP或SWC_GROUP
server:
port: 6088
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: 182.92.122.196:8848
config:
server-addr: 182.92.122.196:8848
file-extension: yaml
group: SWC_GROUP
3.3.3、DataId
同样的命名空间,同样的分组,可以不同的DataId,进行环境的区分配置,进行不同的获取。
总之,namespace是可以用于区分部署环境的,Group和DataID逻辑上区分两个目标对象。