Nacos注册中心是什么?
想象一下一个繁忙的购物中心,里面有很多商店,每个商店都在某个位置提供不同的商品或服务。这个购物中心有一个信息台,人们可以在这里查询任何商店的位置和提供的服务。等到有新的商店开张,或者现有商店搬走,信息台的信息也会随之更新,确保顾客总能找到他们想要的东西。
现在,如果我们把这个购物中心比作微服务架构,那么Nacos注册中心就是那个提供最新信息的信息台。每个微服务启动时,都会向Nacos注册中心“报到”。当有微服务下线或更新时,注册中心也会实时更新这些信息。而当其他服务或用户需要用到某个服务时,它们就会通过Nacos找到所需的服务,并进行通信。
简单来说,Nacos注册中心的作用主要包括:
- 服务注册:微服务在启动时,将自己的信息,如服务地址、端口等注册到Nacos中。
- 服务发现:当微服务需要调用其他服务时,会向Nacos查询所需服务的实时信息,并根据这些信息来发起通信。
- 服务健康检查:Nacos会定期检查注册服务的健康状态,一旦发现服务出现问题,会从注册列表中摘除,确保调用方不会访问到失效的服务。
总之,Nacos注册中心就是微服务架构中维护服务列表、状态和提供服务发现功能的信息集散中心,它确保了服务间的通信是基于最新和健康的服务实例。
在docker中使用Nacos的准备工作
1、准备外部数据库,用来存储Nacos的数据。
2、使用custom.env文件定义Nacos的环境变量
外部数据库数据源和nacos环境配置文件:百度网盘 请输入提取码
记得将环境配置文件中的mysql相关配置改成自己的
3、获取nacos镜像,创建nacos容器并指定custom.env文件
docker run -d \
--name nacos \
--env-file ./nacos/custom.env \
-p 8848:8848 \
-p 9848:9848 \
-p 9849:9849 \
--restart=always \
nacos/nacos-server
确保当前目录下有nacos文件夹(里面是custom.env 也就是nacos环境配置文件),如果mysql也部署在docker中,可以通过--network指定nacos容器和mysql容器在同一个网络
Nacos的使用
1、注册
成功创建nacos容器之后,可以通过http://虚拟机ip地址:8848/nacos/来访问nacos:
首次访问会跳转到登录页,账号密码都是nacos。
然后在需要注册或需要使用服务的服务中引入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.88.130:8848 # nacos地址
如此,配置好的服务就会在启动时自动注册到nacos注册中心
2、使用
服务发现除了要引入nacos依赖以外,由于还需要负载均衡,因此要引入SpringCloud提供的LoadBalancer依赖(nacos依赖也是需要的):
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
配置nacos地址:
spring:
cloud:
nacos:
server-addr: 192.168.150.101:8848
接下来,服务调用者就可以去订阅服务了。不过服务可能有多个实例,而真正发起调用时只需要知道一个实例的地址。
因此,服务调用者必须利用负载均衡的算法,从多个实例中挑选一个去访问。常见的负载均衡算法有:
-
随机
-
轮询
-
IP的hash
-
最近最少访问
-
...
另外,服务发现需要用到一个工具,DiscoveryClient,SpringCloud已经帮我们自动装配,我们可以直接注入使用:
接下来就可以通过DiscoveryClient的方法通过负载均衡算法获取到一个服务地址去调用:
实例:
//2.1根据服务名称获取服务的实例列表
List<ServiceInstance> instances = discoveryClient.getInstances("item-service");
if(CollUtil.isEmpty(instances)){
//判断是否为空
return;
}
//2.2手写负载均衡()这里是最简单的随机负载均衡,从服务列表中获得一个实例
ServiceInstance serviceInstance = instances.get(RandomUtil.randomInt(instances.size()));
//2.1 利用RestTemplate发起http请求,得到http的响应
ResponseEntity<List<ItemDTO>> response = restTemplate.exchange(
serviceInstance.getUri() + "/items?ids={ids}",
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<ItemDTO>>() {
},
Map.of("ids", CollUtil.join(itemIds, ","))
);
//2.2 解析响应
if(!response.getStatusCode().is2xxSuccessful()){
//查询失败,直接结束
return;
}
//查询成功,取出响应体
List<ItemDTO> items = response.getBody();
不知道restTemplate是什么的可以看我的关于restTemplate的文章: