微服务的实现,接触过的有Eureka和Nacos,今天将Nacos回顾学习一下。
基于对B站黑马视频的学习,视频链接:SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务_哔哩哔哩_bilibili
官方文档:什么是 Nacos | Nacos
介绍
Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
使用Nacos可以便捷的实现微服务的部署、管理等。
这次使用的是windows版本的Nacos,需要先将Nacos启动起来
引入依赖
引入Nacos的管理依赖
要想使用Nacos,需要在pom.xml文件中引用Nacos的管理依赖,Nacos的依赖是集成在alibaba(阿里巴巴)依赖下的。
<!--nacos的管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
具体的实现业务引入客户端依赖(服务发现依赖)
<!-- nacos客户端依赖包 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
配置信息
修改appliction.yml配置信息
配置Nacos地址信息,让服务可以连接到Nacos注册中心。8848为Nacos的默认端口号
spring:
application:
name: username # 配置应用的名字
cloud:
nacos:
server-addr: localhost:8848 # nacos地址
spring:
application:
name: orderservice # 应用名字
cloud:
nacos:
server-addr: localhost:8848 # nacos服务地址
启动Nacos
配置完成后,在Nacos文件夹下的bin目录下调出cmd,使用单机模式启动
启动命令 : startup.cmd -m standlone
启动完成后,访问Nacos注册中心,登录后,可以看到
在orderservice中是利用RestTemplate实现了对userservice服务的调用
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
// 2.利用RestTemplate发起http请求,查询用户
// 2.1.url路径
String url = "http://localhost:8081/user/" + order.getUserId();
// 2.2.发送http请求,实现远程调用
User user = restTemplate.getForObject(url, User.class);
// 3.封装user到Order
order.setUser(user);
// 4.返回
return order;
}
可以看到在orderservice是实现了对userservice的调用的
orderservice控制台输出:
userservice控制台输出:
Nacos服务分级存储模型
通过部署多个机房,并把在同一个机房的服务器部署为一个集群,在服务调用时,优先考虑本地集群进行服务调用,提高服务效率。本地集群不可访问,再去访问其他集群。
1、配置application.yml文件,添加集群名称
spring:
cloud:
nacos:
discovery:
cluster-name: SD # 集群名称
在对应的配置下添加,我一共添加了两个集群,启动了三个实例
2、Nacos查看集群
可以看到Nacos中显示两个集群下的不同实例
然后将orderservice添加到SD集群中
实现优先选择本地集群
上面已经将orderservice添加到了SD集群中,为了实现优先选择本地集群,我们需要将服务消费者orderservice调用服务的负载均衡的规则调整一下,具体如下:
# 负载均衡配置
userservice: # 要调用的服务,配置服务的负载均衡规则
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则
将其配置完成后,重启orderservice,并多次调用orderservice的远程调用服务。userservice端口号为8082的在SH集群,其他与orderservice在SD集群。
多次调用后发现,端口号为8082的控制台并无任何输出,相反与orderservice在同一集群的服务控制台输出了服务调用的结果。说明实现了本地集群的优先选择。而且在本地集群中负载均衡规则是随机选择。
我们也可以通过在Nacos中配置服务权重来进行负载均衡。
在SD集群中,将端口号8081的服务权重调整到100。端口号8083的权重保持1,默认不变。
重启userservice服务,再次进行orderservice的多次访问。
通过控制台的输出,会看到8083的服务没有输出,全都在8081服务输出,说明进行了多次调用服务都是调用本地集群下8081的服务。
环境隔离-namespace
基于开发环境、测试环境、生产环境等进行服务的划分
1、在Nacos创建命名空间
2、在application.yml文件中修改服务的环境
将命名空间的Id添加到对应服务的aplication.yml文件中,此处先将oderservice添加加到dev空间
spring:
cloud:
nacos:
discovery:
cluster-name: SD # 集群名称
# 命名空间
namespace: fe2182d7-a817-4b88-b36c-21122420b41e
重启服务,查看Nacos
public默认空间不存在orderservice了
在最上方选择dev开发环境就可以看到配置的orderservice
Nacos配置管理
统一配置管理
统一管理多个微服务的配置,在修改配置时,可以实现多个微服务配置的一起更新,而不需要一个个配置进行修改。
我们需要通过配置管理服务进行实现。在配置进行更新时,配置管理服务会通知关联的服务进行配置的热更新。配置管理服务也是由Nacos实现的。
进入Nacos的配置管理,在dev环境下进行配置管理的实现。dev环境中orderservice和userservice服务各一个。
Data-Id命名规则,服务名称-profiles(环境选择).yaml
关于profiles的使用参考:springboot yml中profiles的妙用,小白必看多环境配置!_yml profiles-CSDN博客
如何获取Nacos中配置的文件哪?
在没有Nacos配置的文件中,Nacos获取配置的过程如下:
当有了Nacos配置的文件,项目启动时,会将Nacos中的配置文件与本地的配置文件进行一个读取合并。
那么如何知道Nacos配置文件的地址哪?
Nacos的地址是存在本地application.yml文件中,为了实现先读取nacos中的配置文件,引入bootstrap.yml文件,它的优先级会比application.yml高很多,项目启动后便会读取bootstrap.yml,所以我们将Nacos地址配置到bootstrap.yml中,相应的在本地application.yml文件中删除重复的。
1、在userservice引入Nacos的配置管理端config依赖
<!--nacos的配置管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2、创建bootstrap.yml,配置相关信息
(此处有点小问题,没有在config中告诉userservice去哪个空间读取配置文件,后面进行了修改)
spring:
application:
name: userservice
profiles:
active: dev # 指定当前使用的环境
cloud:
nacos:
server-addr: localhost:8848 # nacos地址
config:
file-extension: yaml # 文件后缀名
#命名空间
discovery:
namespace: fe2182d7-a817-4b88-b36c-21122420b41e
3、验证是否读取成功
通过@Value注解实现配置文件的读取
@Value("${pattern.dateformat}")
private String dateformat;
@GetMapping("now")
public String now(){
return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateformat));
}
然后运行发现不能拉取,最后发现问题在Nacos配置文件在什么命名空间上,Nacos配置文件被我放在dev环境下,而我在bootstrap文件中没有告诉userservice去哪里读取,它默认会在public中读取。需要修改bootstrap.yml文件
spring:
application:
name: userservice
profiles:
active: dev # 指定当前使用的环境
cloud:
nacos:
server-addr: localhost:8848 # nacos地址
config:
file-extension: yaml # 文件后缀名
#nacos配置文件的地址
namespace: fe2182d7-a817-4b88-b36c-21122420b41e
#命名空间
discovery:
namespace: fe2182d7-a817-4b88-b36c-21122420b41e
之后便可以实现配置的更新
进行拉取服务后也没问题,原本配置文件中日期格式是yyyy-MM HH:mm:ss,现在是nacos配置文件中的格式
配置热更新
如何实现nacos配置文件更新后,服务不需要停止便可以更新配置?
方式一:在@Value注入的变量所在类上添加注解@RefreshScope实现更新
重启服务后,在Nacos中将日期格式修改为yyyy-MM-dd,发布后服务不需要停止,再访问服务就发现日期发生了变化。
方式二:使用@ConfigurationProperties注解
创建属性加载PatternProperties类,将@RefreshScore和@Value注释掉
@Data
@Component #交给ioc容器管理
@ConfigurationProperties(prefix = "pattern") # 配置文件
public class PatternProperties {
private String dateformat;
}
@Autowired
private PatternProperties properties;
@GetMapping("/now")
public String now(){
return LocalDateTime.now().format(DateTimeFormatter.ofPattern(properties.getDateformat()));
}
这种方式也可以进行配置热更新。
多环境配置共享
之前都是多个微服务的配置共享,遇到多环境的配置也可以实现共享
微服务启动时会从Nacos读取多个配置文件:
无论profile如何变化,[spring.application.name].yaml一定会被加载,所以多环境共享配置可以写入这个文件。
在properties文件中添加envSharedValue的变量
为了做比较,启动另一个userservice服务,将其改为test环境
分别访问dev和test的服务,
可以看出每个服务都把envSharedValue读取出来了,而dateformat因为环境的不同,配置文件不同没有读取。
如果碰到本地与远程配置文件的属性一样,但是属性值不一样时,又以谁的为标准?
在本地配置文件中设置name字段为本地,Nacos中设置name字段为Nacos
重启服务后发现
配置文件以Nacos为准
修改Nacos文件再次进行发布
访问结果:
修改本地配置后访没有变化。故得到多种配置的优先级:
若有错误之处欢迎指正修改