赞
踩
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.nacos</groupId>
<artifactId>nacos-spring-context</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</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配置
<!-- --> <?xml version="1.0" encoding="UTF-8"?> <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"> <!-- 自动扫描指定包下的所有类,使其认为spring mvc的控制器 --> <context:component-scan base-package="com.lyb" /> <!--注解驱动,以使得访问路径与方法的匹配可以通过注解配置--> <mvc:annotation-driven /> <!-- Spring Context 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.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.9.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 用于配置管理:版本 0.2.x.RELEASE 对应的是 Spring Boot 2.x 版本 --> <dependency> <groupId>com.alibaba.boot</groupId> <artifactId>nacos-config-spring-boot-starter</artifactId> <version>0.2.3</version> </dependency> <!-- 用于启动服务发现--> <dependency> <groupId>com.alibaba.boot</groupId> <artifactId>nacos-discovery-spring-boot-starter</artifactId> <version>0.2.3</version> </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.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.9.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <!– 版本管理 --> <dependencyManagement> <dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.6.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 用于发布配置和获取配置 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>2.2.6.RELEASE</version> </dependency> <!-- 用于服务注册发现 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2.2.6.RELEASE</version> </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.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</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及以上
<!-- dubbo + nacos时的依赖--> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> <version>2.7.8</version> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-registry-nacos</artifactId> <version>2.7.8</version> </dependency> <!– 未用到配置管理,和服务注册和发现时,可选 --> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-spring-context</artifactId> <version>1.1.1</version> </dependency>
(2)nacos + springboot + dubbo
<!-- dubbo + nacos依赖 --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.8</version> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> <version>2.7.8</version> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-registry-nacos</artifactId> <version>2.7.8</version> </dependency> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>1.4.0</version> </dependency> <!-- 注意:此依赖的版本过高或过低,将导致错误:java.lang.String cannot be cast to java.lang.Class --> <dependency> <groupId>com.alibaba.spring</groupId> <artifactId>spring-context-support</artifactId> <version>1.0.9</version> </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 的单向同步策略。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。