注册中心原理
注册中心可以统一管理项目中的所有服务
- 服务治理中的三个角色分别是什么?
- 服务提供者: 暴露服务接口,供其它服务调用服务
- 消费者: 调用其它服务提供的接口
- 注册中心: 记录并监控微服务各实例状态,推送服务变更信息
- 消费者如何知道提供者的地址?
- 服务提供者会在启动时注册自己信息到注册中心,消费者可以从注册中心订阅和拉取服务信息
- 消费者如何得知服务状态变更?
- 服务提供者通过心跳机制向注册中心报告自己的健康状态,当心跳异常时注册中心会将异常服务剔除,并通知订阅了该服务的消费者
- 当提供者有多个实例时,消费者该选择哪一个?
- 消费者可以通过负载均衡算法,从多个实例中选择一个
Nacos注册中心
Nacos是目前企业中占比最多的注册中心组件。它是阿里巴巴的产品,目前已经加入SpringcloudAlibaba中。
- 官网: Nacos 快速开始
我们基于Docker来部署Nacos的注册中心,首先要准备MySQL数据库表,用来存储Nacos的数据。
- 执行资料中的nacos.sql文件, 创建数据库环境
-
资料中提供了nacos的配置文件, 主要配置了nacos与mysql的连接信息
PREFER_HOST_MODE=hostname
MODE=standalone
SPRING_DATASOURCE_PLATFORM=mysql //数据库类型
// MYSQL_SERVICE_HOST=192.168.1.97 //MySql服务地址, 改为自己的虚拟机IP地址
MYSQL_SERVICE_HOST=mysql //mysql使用了自定义网络, 所以要通过网络名连接
MYSQL_SERVICE_DB_NAME=nacos //数据表名称
MYSQL_SERVICE_PORT=3306 //数据库端口
MYSQL_SERVICE_USER=root //数据库用户名
MYSQL_SERVICE_PASSWORD=123 //数据库登录密码
MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai -
资料中提供了nacos镜像文件, 和配置文件一起上传至root目录下
- 加载本地镜像
-
启动nacos服务
docker run -d
--name nacos
--env-file ./nacos/custom.env
-p 8848:8848
-p 9848:9848
-p 9849:9849
--restart=always
--network hm-net
nacos/nacos-server:v2.1.0-slim
- --restart=always 设置开机自启
- 查看nacos日志
- 访问nacos服务 http://192.168.1.97:8848/nacos/#/login
默认账密: nacos/nacos
服务注册
引入nacos discovery依赖
<!--nacos 服务注册发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
配置Nacos地址
spring:
application:
name: item-service #服务名称
cloud:
nacos :
server-addr:192.168.150.101:8848 #nacos地址
模拟多实例部署
服务发现
消费者需要连接nacos以拉取和订阅服务,因此服务发现的前两步与服务注册一样,后面再加上服务调用
-
引入nacos discovery依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> -
配置nacos地址
spring:
application:
name: cart-service #服务名称
cloud:
nacos :
server-addr: 192.168.1.97:8848 #nacos地址 -
服务发现
@Service
@RequiredArgsConstructor
public class CartServiceImpl extends ServiceImpl<CartMapper, Cart> implements ICartService {// 使用discoveryClient客户端进行服务拉取 private final DiscoveryClient discoveryClient; ... ... private void handleCartItems(List<CartVO> vos) { // 1.获取商品id Set<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet()); // 2.查询商品 // 2.1 根据服务名称获取服务的实例列表 List<ServiceInstance> instances = discoveryClient.getInstances("item-service"); if(CollUtil.isEmpty(instances)) { return; } // 2.2 手写负载均衡,从实例列表中随机挑选一个实例 ServiceInstance instance = instances.get(RandomUtil.randomInt(instances.size())); //2.3 使用restTemplate远程调用商品服务 ResponseEntity<List<ItemDTO>> response = restTemplate.exchange( instance.getUri() + "/items?ids={ids}", HttpMethod.GET, null, new ParameterizedTypeReference<List<ItemDTO>>() { }, Map.of("ids", CollUtil.join(itemIds, ",")) ); ... ... }
}
-
购物车模块调用商品模块, 2个商品服务实例被随机访问