Nacos官方文档地址: https://nacos.io/zh-cn/docs/what-is-nacos.html
(1)nacos 不仅是注册中心,也是配置中心;目前几乎支持所有主流类型的“服务”的发现、配置和管理,如: Kubernetes Service(K8s)、gRPC、 Dubbo RPC Service和Spring Cloud RESTful Service
(2)Nacos提供基于DNS和基于RPC的服务发现,即能被用来支持https/http的服务注册与发现;也支持RPC,如dubbo的服务注册与发现。
(3)与dubbo使用的zookeeper相比,两者差异较大。zookeeper是一种分布式的协调服务,天生作为分布式数据一致性场景下的解决方案,故zookeeper是CP原则,牺牲可用性,保证一致性;在极端情况下(master选举期间)服务会对外停止。Nacos是一种去中心化的框架,属于CAP理论中的AP架构,支持最终一致性,在分布式服务发现与注册具有很好的性能。
注:zookeeper满足CP原则,在进行数据同步时,因一致性要求(Leader-Follower),不允许客户端读写,程序阻塞。
(4)CAP原则:指的是分布式系统中,一致性(C)、可用性(A)、分区容错性( P );三个要素同时最多实现两点,不可能三者兼得。
一致性:在分布式系统中所有数据备份,在同一时刻是否同样的值。
可用性:在集群中一部分节点故障后,整体能否响应客户端的读写请求。(对数据更新具有高可用性)
分区容错性:系统如果不能在时限内达成数据一致性,则意味着发生了分区的情况,必须就当前操作在C和A之间做选择。
(5)动态配置服务:动态修改配置并实时生效,消除了配置变更时重新部署应用和服务的需要,让配置管理变得更加高效和敏捷,适合于“配置优先”的服务开发。
(6)保护阈(yu)值:可以设置0-1之间的浮点数,其实是个比例值(当前服务健康实例数/当前服务总实例数);意义至于,当服务健康实例数/总实例数 < 保护阈值,说明健康的实例数不多了,这时候会触发保护阈值状态为true,那么nacos会把所有(健康+不健康的)实例全部提供给消费者;消费者可能会访问到不健康的实例从而请求失败,但比造成雪崩要好,牺牲部分请求,保证了整个系统可用。
常用的注解:https://nacos.io/zh-cn/docs/open-api.html
(1)nacos-spring
① @EnableNacosConfig(globalProperties = @NacosProperties(serverAddr = “127.0.0.1:8848”)) :注解启用 Nacos Spring 的配置管理服务。
② @EnableNacosDiscovery(globalProperties = @NacosProperties(serverAddr = “127.0.0.1:8848”)) :注解开启 Nacos Spring 的服务发现功能。
③ @Configuration:配置spring并启动spring容器
(2)nacos-spring 和nacos-springboot
① @NacosPropertySource(dataId = “example”, autoRefreshed = true):配置属性值,以dataId和groupId划分维度; autoRefreshed表示数据被更改后是否自动刷新。
② @NacosValue(value = “${useLocalCache:false}”, autoRefreshed = true):设置属性值,表示可自动刷新。
③ @NacosInjected:用于注入 Nacos 的 NamingService 实例。
(3)nacos-springcloud
① @RefreshScope:实现配置自动更新;此注解需放在有@Value注解的类上
② @EnableDiscoveryClient:开启服务注册发现功能
(1)多版本下载列表:https://github.com/alibaba/nacos/releases
(2)Linux下载:wget https://github.com/alibaba/nacos/releases/download/2.0.3/nacos-server-2.0.3.tar.gz
(3)可通过F12查看具体下载地址,如下图(zip是Windows版本,tar.gz是Linux版本)
(1)解压
tar -zxvf nacos-server-2.0.3.tar.gz
(2)可移动到指定的目录
mv nacos /app
可能遇到的问题:
移动无权限:mv: cannot move ‘nacos’ to ‘/app/nacos’: Permission denied
解决:chmod -R 777 /app
① -R是目录下所有文件
② r(Read,读取,权限值为4):对文件而言,具有读取文件内容的权限;对目录来说,具有浏览目 录的权限。
③ w(Write,写入,权限值为2):对文件而言,具有新增、修改文件内容的权限;对目录来说,具有删除、移动目录内文件的权限。
④ x(eXecute,执行,权限值为1):对文件而言,具有执行文件的权限;对目录了来说该用户具有进入目录的权限。
(3)进入bin
cd /app/nacos/bin
(4)单机模式启动(默认是集群启动)
sh startup.sh -m standalone
① 问题:ERROR: Please set the JAVA_HOME variable in your environment, We
need java(x64)! jdk8 or later is better! !!
② 解决:在服务器中安装JDK1.8
(5)默认访问模板
默认模板:http://ip:8848/nacos/index.html
请求地址:http://127.0.0.1:8848/nacos/index.html
管理账户: nacos / nacos
(6)登录界面
① 命名空间:常用于对不同环境的配置区分隔离;不同命名空间,可以有相同的Group和Data ID的配置。
② 配置管理:一个配置文件通常就是一个配置集;配置集由Data ID和Group划分维度,通常Data ID以类包的命名规则保证唯一性,Group在Data ID相同的情况下,用于区分不同的配置。
注:查看版本的地址:https://mvnrepository.com/artifact/groupId(如:com.alibaba.nacos)/artifactId(如:nacos-spring-context)
(1)pom.xml 配置
<dependency>
<groupId>com.alibaba.nacosgroupId>
<artifactId>nacos-spring-contextartifactId>
<version>1.1.1version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>4.3.7.RELEASEversion>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
dependency>
(2)nacos的配置类(在com.lyb下,需要用到nacos配置的类,必须是同级包或其子包下,亦或者需要用此配置的需指定扫描到它)
@Configuration
@EnableNacosConfig(globalProperties = @NacosProperties(serverAddr = "127.0.0.1:8848")) // 启动配置管理
@EnableNacosDiscovery(globalProperties = @NacosProperties(serverAddr = "127.0.0.1:8848")) // 启动服务发现与注册
@NacosPropertySource(dataId = “example”, autoRefreshed = true) // 配置管理使用的
public class NacosConfiguration {
}
(3)控制层(在com.lyb.controller包下,必须是配置类的子包或同级包)
// ① 获取配置控制层
@Controller
@RequestMapping("config")
public class NacosConfigController {
@NacosValue(value = "${useLocalCache:false}", autoRefreshed = true)
private boolean useLocalCache;
@RequestMapping(value = "/get", method = RequestMethod.GET)
@ResponseBody
public boolean get() {
return useLocalCache;
}
}
// ② 服务发现控制层
@Controller
@RequestMapping("discovery")
public class NacosDiscoveryController {
@NacosInjected
private NamingService namingService;
@RequestMapping(value = "/get", method = RequestMethod.GET)
@ResponseBody
public List<Instance> get(@RequestParam String serviceName) throws NacosException {
return namingService.getAllInstances(serviceName);
}
}
(4)spring-mvc配置
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.lyb" />
<mvc:annotation-driven />
<context:annotation-config />
beans>
(5)发布
① 发布配置
curl -X POST “http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=example&group=DEFAULT_GROUP&content=useLocalCache=true”
② 注册实例
curl -X POST “http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=example&ip=127.0.0.1&port=8080”
注:0.2.x.RELEASE版本:https://mvnrepository.com/artifact/com.alibaba.boot/nacos-config-spring-boot-starter
(1)pom.xml配置
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.3.9.RELEASEversion>
<relativePath/>
parent>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>com.alibaba.bootgroupId>
<artifactId>nacos-config-spring-boot-starterartifactId>
<version>0.2.3version>
dependency>
<dependency>
<groupId>com.alibaba.bootgroupId>
<artifactId>nacos-discovery-spring-boot-starterartifactId>
<version>0.2.3version>
dependency>
dependencies>
(2)Spring Boot的启动类Application,在com.lyb包下
@SpringBootApplication
@NacosPropertySource(dataId = "example", autoRefreshed = true)
public class NacosSpringBootProviderMain implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(NacosSpringBootProviderMain.class, args);
}
// 应用名,可配置文件配置,默认: name:nacos-springboot-provider
@Value("${spring.application.name:nacos-springboot-provider}")
private String applicationName;
@NacosInjected
private NamingService namingService;
@Override
public void run(String... args) throws Exception {
// 通过NamingService服务注册实例到注册中心(参数可用配置方式,提供外部访问的本地服务的ip和端口号)
namingService.registerInstance(applicationName, "192.168.50.118", 8040);
}
}
(3)控制层,在com.lyb.controller包下
// 获取配置管理的参数(与Nacos Spring相似)
@Controller
@RequestMapping("config")
public class NacosConfigController {
@NacosValue(value = "${useLocalCache:false}", autoRefreshed = true)
private boolean useLocalCache;
public void setUseLocalCache(boolean useLocalCache) {
this.useLocalCache = useLocalCache;
}
@RequestMapping(value = "/get", method = RequestMethod.GET)
@ResponseBody
public boolean get() {
return useLocalCache;
}
}
// 获取发布的服务
@Controller
@RequestMapping("discovery")
public class NacosDiscoveryController {
@Resource
private RestTemplate restTemplate;
@NacosInjected
private NamingService namingService;
@RequestMapping(value = "/getAll", method = RequestMethod.GET)
@ResponseBody
public List<Instance> get(@RequestParam String serviceName) throws NacosException {
return namingService.getAllInstances(serviceName);
}
@RequestMapping("/get")
@ResponseBody
public String getInfoByService(@RequestParam String name) throws Exception {
// 根据服务名从注册中心获取一个健康的服务实例
Instance instance = namingService.selectOneHealthyInstance("nacos-springboot-provider");
String url = String.format("http://%s:%d/discovery/hello?name=%s", instance.getIp(), instance.getPort(), name);
String result = restTemplate.getForObject(url, String.class);
return String.format("消费者请求url:%s ;调用结果:%s", url, result);
}
}
(4)application.properties的配置
# 应用名称
spring.application.name=nacos-springboot-provider
# 端口号
server.port=8040
# 启动配置管理
nacos.config.server-addr=127.0.0.1:8848
# 启动服务发现
nacos.discovery.server-addr=127.0.0.1:8848
# 命名空间,对于相同的data ID和groupId时,常用于区分测试和生产。默认nacos.config.namespace = public
# nacos.config.namespace=test
(5)启动测试
① cmd命令-> 配置管理:发布配置和获取配置
curl -X POST “http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=example&group=DEFAULT_GROUP&content=useLocalCache=true”
curl -X GET “http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=example&group=DEFAULT_GROUP”
② cmd命令-> 启动服务:注册实例和查询服务
curl -X POST “http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=example&ip=127.0.0.1&port=8040”
curl -X GET “http://127.0.0.1:8848/nacos/v1/ns/service?serviceName=example”
③ 启动程序(通过发布配置和注册实例,获取参数最新值和服务)
http://localhost:8040/config/get
http://localhost:8040/discovery/get?serviceName= nacos-springboot-provider
(1)pom.xml 配置说明
注:pom.xml:版本说明:https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E
经测试,2.2.7. RELEASE版本有问题,无法实现获取配置的参数,其它版本正常。
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.3.9.RELEASEversion>
<relativePath/>
parent>
<!– 版本管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>2.2.6.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
<version>2.2.6.RELEASEversion>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
<version>2.2.6.RELEASEversion>
dependency>
dependencies>
(2)启动类(在com.lyb包下)
@SpringBootApplication
@EnableDiscoveryClient //开启服务注册发现功能
public class NacosSpringCloudApplication {
......
@LoadBalanced // 消费者项目使用,用于访问提供者
@Bean
public RestTemplate restTemplate() {return new RestTemplate();}
}
(3)控制层(在com.lyb.controller包下):消费者和提供者参数获取方式相同
@RestController
@RequestMapping("config")
@RefreshScope
public class NacosConfigController {
@Value("${useLocalCache:false}")
private boolean useLocalCache;
@RequestMapping("/get")
public boolean get() {
return useLocalCache;
}
}
(4)服务提供者和服务消费者
// ① 生产者提供一个请求接口,如: http://nacos-springcloud-provider/echo/string (string可变参数)
@RequestMapping(value = "/echo/{string}", method = RequestMethod.GET)
public String echo(@PathVariable String string) {
return “Hello! Nacos Discovery” + string;
}
// ② 消费者使用提供的请求接口,外部请求消费者:http://192.168.50.118:8070/echo/string
@RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
public String echo(@PathVariable String str) {
return restTemplate.getForObject(" http://nacos-springcloud-provider/echo /" + str, String.class);
}
(5)项目属性配置
① bootstrap.properties
# 发布配置和获取配置地址
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
注:配置管理需要放置文件bootstrap.properties内,不然无法生效参数发布和获取。解决办法,可以引入下列依赖:
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-bootstrapartifactId>
dependency>
② application.properties
# 服务注册地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
# 服务应用名
spring.application.name=nacos-service-provider
③ 发布和获取配置属性的Data ID 的命名规范,如下:
p r e f i x − {prefix}- prefix−{spring.profiles.active}. f i l e − e x t e n s i o n ( 1 ) p r e f i x 默 认 为 s p r i n g . a p p l i c a t i o n . n a m e 的 值 , 也 可 以 通 过 配 置 项 s p r i n g . c l o u d . n a c o s . c o n f i g . p r e f i x 来 配 置 ( 2 ) s p r i n g . p r o f i l e s . a c t i v e 即 为 当 前 环 境 对 应 的 p r o f i l e ; 当 s p r i n g . p r o f i l e s . a c t i v e 为 空 时 , 对 应 的 连 接 符 − 也 将 不 存 在 , 即 : {file-extension} (1) prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置 (2) spring.profiles.active 即为当前环境对应的 profile;当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,即: file−extension(1)prefix默认为spring.application.name的值,也可以通过配置项spring.cloud.nacos.config.prefix来配置(2)spring.profiles.active即为当前环境对应的profile;当spring.profiles.active为空时,对应的连接符−也将不存在,即:{prefix}.${file-extension}
(3) file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 和yaml 类型
发布配置属性: curl -X POST “http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos-springcloud-consumer.properties&group=DEFAULT_GROUP&content=useLocalCache=true”
# 实现dubbo的服务分组和使用不同的命令空间,dubbo的配置
dubbo.registry.address=nacos://127.0.0.1:8848?namespace=test&group=test
(1)nacos + spring + dubbo
注:dubbo2.7.7版本不支持,需升级到2.7.8及以上
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubboartifactId>
<version>2.7.8version>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-registry-nacosartifactId>
<version>2.7.8version>
dependency>
<!– 未用到配置管理,和服务注册和发现时,可选 -->
<dependency>
<groupId>com.alibaba.nacosgroupId>
<artifactId>nacos-spring-contextartifactId>
<version>1.1.1version>
dependency>
(2)nacos + springboot + dubbo
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-spring-boot-starterartifactId>
<version>2.7.8version>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubboartifactId>
<version>2.7.8version>
dependency>
<dependency>
<groupId>org.apache.dubbogroupId>
<artifactId>dubbo-registry-nacosartifactId>
<version>2.7.8version>
dependency>
<dependency>
<groupId>com.alibaba.nacosgroupId>
<artifactId>nacos-clientartifactId>
<version>1.4.0version>
dependency>
<dependency>
<groupId>com.alibaba.springgroupId>
<artifactId>spring-context-supportartifactId>
<version>1.0.9version>
dependency>
(3)nacos + springboot的dubbo配置
dubbo.protocol.name=dubbo
# 表示 dubbo 自动扫描并使用可用端口(从20880开始递增),避免了端口冲突的问题
dubbo.protocol.port=-1
dubbo.registry.address=nacos://127.0.0.1:8848
dubbo.application.name=dubbo-nacos-springboot-provider
dubbo.consumer.check=false
(1)如果注册服务中间件用的是zookeeper的迁移方案
① 改造 dubbo 应用,将服务注册改为双注册(同时注册到 zookeeper 与 nacos),等所有应用改造完成后再统一切换到 nacos;
② 使用迁移工具,将 zookeeper 上注册的服务统一迁移到 nacos,然后慢慢修改应用,不必等完全迁移完即可享受 nacos 带来的新特性。
③ 方案区别
方案一:影响较大,需要多所有应用到zk的项目同时启动一遍,而且启动过程中会存在读取不到服务的情况,目前不考虑这种方案
方案二:需要用到nacos 提供了nacosSync同步工具,影响较小,需要对nacosSync迁移工具的同步策略做好规划。
(1)nacosSync 是一个支持多种注册中心的同步组件,基于 SpringBoot 开发框架;
(2)nacosSync可实现从 zookeeper 到 nacos 的双向同步功能,但双向同步可能有风险,新加的nacos不能保证稳定性,若出现数据有误,则同步到zookeeper上会带来故障。所以可以采取比较保守的 zookeeper 到 nacos 的单向同步策略。