目录
一.什么是Nacos?
二.什么是注册中心?
1.注册中心的定义:
2.为什么需要使用注册中心?
3.注册中心原理:
三.Nacos的使用:
1.安装与启动Nacos:
2.集成 Nacos 服务注册与发现:
(1)导入Nacos依赖:
(2)配置Nacos注册中心:
(3)使用Nacos发现并调用服务:
3.常见错误以及解决方案:
总结:
资源参考:SpringCloud微服务开发与实战 --- java黑马商城项目微服务实战开发文档
一.什么是Nacos?
Nacos 是阿里巴巴开源的一款服务发现、配置管理和动态 DNS的工具,适用于微服务架构。它是 Spring Cloud Alibaba 生态的重要组件,用于解决微服务之间的服务注册与发现,以及配置的集中管理问题。
- 特点:服务注册与发现 + 配置管理一体化,支持健康检查和动态配置。
- 优点:支持多种协议(HTTP、gRPC),UI 管理方便,适用于 Spring Cloud。
二.什么是注册中心?
1.注册中心的定义:
注册中心是微服务架构中的一个核心组件,用于服务注册与发现。在分布式系统中,多个微服务实例需要互相通信,但每个服务的地址可能动态变化,比如因为自动扩展、实例重启、故障恢复等。因此,注册中心充当了服务地址的目录,实现了服务实例的动态管理和发现,保证服务间的高效通信。
2.为什么需要使用注册中心?
假如商品微服务被调用较多,为了应对更高的并发,我们进行了多实例部署:
此时,每个item-service
的实例其IP或端口不同,问题来了:
-
item-service这么多实例,cart-service如何知道每一个实例的地址?
-
http请求要写url地址,
cart-service
服务到底该调用哪个实例呢? -
如果在运行过程中,某一个
item-service
实例宕机,cart-service
依然在调用该怎么办? -
如果并发太高,
item-service
临时多部署了N台实例,cart-service
如何知道新实例的地址?
带着这四个问题,我们开始学习注册中心:
在微服务架构中,每个服务可能分布在不同的节点或容器内。由于这些服务的IP地址和端口号可能会变化,传统的静态配置方法无法满足需求。注册中心解决了以下问题:
- 动态服务地址管理:当服务实例启动或关闭时,地址会自动更新到注册中心。
- 自动负载均衡:注册中心记录了所有可用的服务实例,可以根据策略实现负载均衡。
- 故障恢复:如果某个实例不可用,注册中心会标记其状态,避免请求发送到无效实例。
- 去中心化:客户端可以动态发现服务,不需要硬编码服务地址。
3.注册中心原理:
按照上面箭头进行流程分析如下:
服务启动时就会注册自己的服务信息(服务名、IP、端口)到注册中心
调用者可以从注册中心订阅想要的服务,获取服务对应的实例列表(1个服务可多实例部署)
调用者自己对实例列表负载均衡,挑选一个实例
调用者向该实例发起远程调用
当服务提供者的实例宕机或者启动新实例时,调用者如何得知呢?(心跳请求机制)
服务提供者会定期向注册中心发送请求,报告自己的健康状态(心跳请求机制)
当注册中心长时间收不到提供者的心跳时,会认为该实例宕机,将其从服务的实例列表中剔除
当服务有新实例启动时,会发送注册服务请求,其信息会被记录在注册中心的服务实例列表
当注册中心服务列表变更时,会主动通知微服务,更新本地服务列表
三.Nacos的使用:
1.安装与启动Nacos:
我们基于Docker来部署Nacos的注册中心,首先我们要准备MySQL数据库表,用来存储Nacos的数据。由于是Docker部署,所以我们需要将资料中的SQL文件导入到我们自己的Docker中的MySQL容器中:Nacos的相关资料-CSDN博客
导入后再Linux虚拟机内的/root/nacos目录内导入custom.env文件,文件内容见Nacos的相关资料-CSDN博客
进入root目录后执行下面的Docker命令:
docker run -d \
--name nacos \
--env-file ./nacos/custom.env \
-p 8848:8848 \
-p 9848:9848 \
-p 9849:9849 \
--restart=always \
nacos/nacos-server:v2.1.0-slim
随后启动完成后,访问下面的地址:http://虚拟机IP地址:8848/nacos/,首次访问会跳转到登录页,账号密码都是nacos。
2.集成 Nacos 服务注册与发现:
如果我们想在cart-service模块远程调用item-service的接口,我们进行下面操作:
(1)导入Nacos依赖:
在两模块导入依赖:
<!--nacos 服务注册发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
任何一个微服务都可以调用别人,也可以被别人调用,即可以是调用者,也可以是提供者。
(2)配置Nacos注册中心:
在item-service的application.yml中添加Nacos地址配置:
spring:
application:
name: item-service # 服务名称
cloud:
nacos:
server-addr: 虚拟机IP地址:8848 # nacos地址
在cart-service的application.yml中添加Nacos地址配置:
spring:
application:
name: cart-service # 服务名称
cloud:
nacos:
server-addr: 虚拟机IP地址:8848 # nacos地址
(3)使用Nacos发现并调用服务:
可参考下面博客进行理解: 微服务架构 --- OpenFeign的项目实战操作-CSDN博客
在启动类中添加
@EnableDiscoveryClient
注解:
@MapperScan("com.hmall.cart.mapper")
@SpringBootApplication
@EnableDiscoveryClient
public class CartApplication {
public static void main(String[] args) {
SpringApplication.run(CartApplication.class, args);
}
//RestTemplate
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
随后在Service层使用discoveryClient客户端来完成远程服务的拉取:
@Service
@RequiredArgsConstructor //推荐restTemplate以构造方法导入,这个注解仅构造final修饰的成员属性
public class CartServiceImpl extends ServiceImpl<CartMapper, Cart> implements ICartService {
private final RestTemplate restTemplate;
//用discoveryClient客户端完成服务的拉取
private final DiscoveryClient discoveryClient;
private void handleCartItems(List<CartVO> vos) {
// TODO 1.获取商品id
Set<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet());
// 2.查询商品
List<ItemDTO> items = itemClient.queryItemByIds(itemIds);
// 2.1根据服务名称获取服务的实例列表
List<ServiceInstance> instances = discoveryClient.getInstances("item-service");
if(CollUtils.isEmpty(instances)){
return ;
}
// 2.2手写负载均衡,从实例列表中挑选实例
ServiceInstance serviceInstance = instances.get(RandomUtil.randomInt(instances.size()));
// 2.3利用RestTemplate发起http请求,得到http的响应
ResponseEntity<List<ItemDTO>> response = restTemplate.exchange(
serviceInstance.getUri() + "/items?{ids}",
HttpMethod.GET,
null,
//写集合泛型的class,因为new的对象可以拿到泛型,随后用反射就可以拿到对象的数据类型返回值
new ParameterizedTypeReference<List<ItemDTO>>() {},
Map.of("ids",CollUtils.join(itemIds,","))//集合拼接
);
// 2.4解析响应
if(!response.getStatusCode().is2xxSuccessful()){
//查询失败,直接结束11
return ;
}
List<ItemDTO> items = response.getBody();
if (CollUtils.isEmpty(items)) {
return;
}
// 剩余操作...
}
}
3.常见错误以及解决方案:
-
无法连接到 Nacos 服务器:
- 检查 Nacos 是否启动,并确保端口号 8848 未被占用。
- 如果是集群模式,检查集群节点的状态。
-
服务无法注册到 Nacos:
- 检查
application.yml
中的服务名是否正确。 - 确保网络连接正常,且服务能访问到 Nacos。
- 检查
-
配置未刷新:
- 检查是否在 Controller 中添加了
@RefreshScope
注解。 - 检查是否已触发
/actuator/refresh
端点。
- 检查是否在 Controller 中添加了
总结:
Nacos 是一款功能强大的工具,集成了服务注册与发现、配置管理和动态 DNS等功能,非常适合微服务架构。通过与 Spring Boot 的深度集成,开发者可以轻松地使用 Nacos 管理微服务的生命周期和配置,提升系统的灵活性与可维护性。所以我们可以通过使用Nacos来轻松的管理微服务模块。