Spring Cloud 整合 Nacos

1.服务注册与发现

1.1 注册中心原理

在微服务远程调用的过程中,包括俩个角色:

  • 服务提供者:提供接口供其他微服务访问
  • 服务消费者:调用其他微服务接口

在大型微服务项目中,服务提供者的数量会非常多,为了管理这些服务就引入注册中心的概念。

image-20231221000203281

1.2 数据库准备 用作持久化

我们基于Docker来部署Nacos的注册中心,首先我们要准备MySQL数据库表,用来存储Nacos的数据。由于是Docker部署,所以大家需要将资料中的SQL文件(github上可以找到这个sql文件)导入到你Docker中的MySQL容器中:

image-20231221001245661

然后修改nacos文件中的custom.env文件

1
2
3
4
5
6
7
8
9
PREFER_HOST_MODE=hostname
MODE=standalone
SPRING_DATASOURCE_PLATFORM=mysql
MYSQL_SERVICE_HOST=192.168.163.128//宿主机ip地址修改为自己的
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目录。进入root目录执行:

1
2
3
4
5
6
7
8
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://192.168.163.128:8848/nacos/,注意将`192.168.163.128`替换为你自己的虚拟机IP地址。

首次访问会跳转到登录页,账号密码都是nacos

1.3 服务注册

1.3.1 添加依赖

1
2
3
4
5
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>${latest.version}</version>
</dependency>

1.3.2 配置nacos

application.yml中添加nacos地址配置:

1
2
3
4
5
6
spring:
application:
name: item-service # 服务名称
cloud:
nacos:
server-addr: 192.168.163.128:8848 # nacos地址

1.4 服务发现

服务的消费者要去nacos订阅服务,这个过程就是服务发现,步骤如下:

  • 引入依赖
  • 配置Nacos地址
  • 发现并调用服务

1.4.1 引入依赖

1
2
3
4
5
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>${latest.version}</version>
</dependency>

可以发现,这里Nacos的依赖于服务注册时一致,这个依赖中同时包含了服务注册和发现的功能。因为任何一个微服务都可以调用别人,也可以被别人调用,即可以是调用者,也可以是提供者。

1.4.2 配置Nacos地址

1
2
3
4
spring:
cloud:
nacos:
server-addr: 192.168.163.128:8848

1.4.3 发现并调用服务

服务发现需要用到一个工具,DiscoveryClient,SpringCloud已经帮我们自动装配,我们可以直接注入使用:

1
2
3
4
5
6
7
8
@Service
@RequiredArgsConstructor
public class CartServiceImpl extends ServiceImpl<CartMapper, Cart> implements ICartService {

// private final IItemService itemService;
private final RestTemplate restTemplate;//发http请求进行服务调用

private final DiscoveryClient discoveryClient;//在nacos注册中心中发现服务

其中 DiscoveryClient用于服务发现:RestTemplate用于服务调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// TODO 1.获取商品id
Set<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet());
// 2.查询商品
//2.1 发现商品服务实例列表
List<ServiceInstance> instances = discoveryClient.getInstances("item-service");
if(CollUtils.isEmpty(instances)){
return;
}
//2.2 负载均衡 选择一个服务实例
ServiceInstance instance = instances.get(RandomUtil.randomInt(instances.size()));
// List<ItemDTO> items = itemService.queryItemByIds(itemIds);
// 2.1.利用RestTemplate发起http请求,得到http的响应
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.2.解析响应
if(!response.getStatusCode().is2xxSuccessful()){
// 查询失败,直接结束
return;
}

利用RestTemplate调用了解即可,因为更合适的还是利用Openfeign组件来进行服务调用。