> 技术文档 > Nacos-服务注册,服务发现(一)

Nacos-服务注册,服务发现(一)


nacos快速入手

Nacos是Spring Cloud Alibaba的组件, Spring Cloud Alibaba遵循Spring Cloud中定义的服务注册, 服

务发现规范. 因此使⽤Nacos和使⽤Eureka对于微服务来说,并没有太⼤区别.

主要差异在于:

  • Eureka需要⾃⼰搭建⼀个服务, Nacos不⽤⾃⼰搭建服务, 组件已经准备好了, 只需启动即可.
  • 对应依赖和配置不同

1.引入spring-cloud-alibaba的依赖

在⽗⼯程的pom⽂件中的 中引⼊Spring Cloud Alibaba的依赖:

 2022.0.0.0-RC2 com.alibaba.cloud spring-cloud-alibaba-dependencies ${spring-cloud-alibaba.version} pom import

2.引入Nacos相关的依赖

在order-service和product-service中引⼊nacos依赖

 com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery  //引⼊Load Balance依赖  org.springframework.cloud spring-cloud-loadbalancer 

3.修改配置

配置项 Key 默认值 说明 服务端地址 spring.cloud.nacos.discovery.server-addr ⽆ Nacos Server 启动监听的ip地址和端⼝
spring: application: name: product-service cloud: nacos: discovery: server-addr: 110.41.51.65:10020

4.远程调用

修改IP为项目名称

@Servicepublic class OrderService { @Autowired private OrderMapper orderMapper; @Autowired private RestTemplate restTemplate; public OrderInfo selectOrderById(Integer orderId){ OrderInfo orderInfo = orderMapper.selectOrderById(orderId); String url = \"\" + orderInfo.getProductId(); ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class); orderInfo.setProductInfo(productInfo); return orderInfo; }}

为restTemplate添加负载均衡注解 @LoadBalanced

@Configurationpublic class BeanConfig { @LoadBalanced @Bean public RestTemplate restTemplate(){ return new RestTemplate(); }}

5.测试

启动order-service 和product-service服务, 观察Nacos的管理界⾯, 发现order-service 和product-service 都注册在Nacos上了。

测试接口:http://127.0.0.1:8080/order/1

启动多个服务,测试负载均衡

启动三个 product-service 实例

观察nacos:

多次访问,http://127.0.0.1:8080/order/1,观察日志

常见问题

  1. java.net.UnknownHostException

    2023-12-25T19:04:23.803+08:00 ERROR 25892 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.web.client.ResourceAccessException: I/O error on GET request for \"\": product-service] with root causejava.net.UnknownHostException: product-service at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:572) ~[na:na] at java.base/java.net.Socket.connect(Socket.java:633) ~[na:na] at java.base/java.net.Socket.connect(Socket.java:583) ~[na:na] at java.base/sun.net.NetworkClient.doConnect(NetworkClient.java:183) ~[na:na] at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:534) ~[na:na]......

    检查是否添加 LoadBalance 依赖

     org.springframework.cloud spring-cloud-loadbalancer
  2. 服务注册失败

    可能没有报错⽇志, 或者报错⽇志如下(与版本有关)

    Parameter 0 of method inetIPv6Utils incom.alibaba.cloud.nacos.util.UtilIPv6AutoConfiguration required a bean of type \'org.springframework.cloud.commons.util.InetUtilsProperties\' that could not be found.The injection point has the following annotations: - @org.springframework.beans.factory.annotation.Autowired(required=true)Action:Consider defining a bean of type \'org.springframework.cloud.commons.util.InetUtilsProperties\' in your configuration.

    检查Spring Cloud Alibaba版本是否正确 参考:版本发布说明-阿里云Spring Cloud Alibaba官网

Nacos负载均衡

Nacos⽀持多种负载均衡策略, 包括权重, 同机房, 同地域, 同环境等.

服务下线

当某一个节点上接口的性能较差时,我们可以第一时间对该节点进行下线,防止对服务造成一定的影响。(问ai再确认一下)

步骤:服务详情 → 下线

点击下线后,再次请求接⼝,会发现该服务没有请求进来了,再次单击上线, 该节点会继续收到请求。

权重配置

权重配置,配置的是这个节点流量权重,权重大就代表流量大,权重小就代表流量小。

1.修改权重配置

操作: 详情 → 对应节点 → 编辑 → 修改权重值

权重配置默认为1,这里测试改成 0.1

2.开启 Nacos 负载均衡策略

由于Spring Cloud LoadBalance组件⾃⾝有负载均衡配置⽅式, 所以不⽀持Nacos的权重属性配置。

我们需要开启Nacos的负载均衡策略, 让权重配置⽣效

参考:如何解决MSE Nacos上修改服务实例的权重不生效问题_微服务引擎(MSE)-阿里云帮助中心

#开启nacos的负载均衡策略spring: cloud: loadbalancer: nacos: enabled: true

3.测试权重配置

启动服务,访问多次接⼝,观察结果, 会发现9091端⼝号的实例接收的请求明显⽐另外两个实例少。

整体流量⽣效, 局部流量不是严格按照设置的⽐例进⾏分配的

常见问题

修改权重时, 可能会报错:

原因:Nacos 采⽤ raft 算法来计算 Leader, 并且会记录前⼀次启动的集群地址, 当服务器 IP 改变时

导致 raft 记录的集群地址失效, 导致选 Leader 出现问题. (⽹络环境发⽣变化时, IP地址也会发⽣变化)

解决办法:删除 Nacos 根⽬录下 data ⽂件夹下的 protocol ⽂件夹即可。

Nacos 集群优先访问

Nacos把同⼀个机房内的实例, 划分为⼀个集群. 所以同集群优先访问, 在⼀定程度上也可以理解为同房优先访问.

微服务架构中, ⼀个服务通常有多个实例共同提供服务, 这些实例可以部署在不同的机器上, 这些机器

可以分布在不同的机房, ⽐如product-service:

实例1: 分布在上海机房 实例2: 分布在上海机房 实例3: 分布在北京机房 实例4: 分布在北京机房

微服务访问时, 应尽量访问同机房的实例. 当本机房内实例不可⽤时, 才访问其他机房的实例.

⽐如order-service 在上海机房, product-service 在北京和上海机房都有实例, 那我们希望可以优先访

问上海机房, 如果上海机房没有实例, 或者实例不可⽤, 再访问北京机房的实例. 通常情况下, 因为同一

个机房的机器属于⼀个局域⽹, 局域⽹访问速度更快⼀点.

为实例配置集群名称

1.为product-service配置集群名称

spring: cloud: nacos: discovery: cluster-name: SH #集群名称: 上海集群

重启服务, 观察Nacos控制台, SH集群下多了⼀个实例

复制product-service启动配置, 添加VM Option

设置9091端⼝号的实例, 机房为BJ

-Dserver.port=9091 -Dspring.cloud.nacos.discovery.cluster-name=BJ

设置9092端⼝号的实例, 机房为BJ

-Dserver.port=9092 -Dspring.cloud.nacos.discovery.cluster-name=BJ

观察Nacos, BJ集群下多了两个实例

2.为order-service配置集群名称

spring: cloud: nacos: discovery: cluster-name: SH #集群名称: 上海集群

开启Nacos负载均衡策略

spring: cloud: loadbalancer: nacos: enabled: true

测试

启动服务

  1. 对接⼝访问多次, 观察⽇志, 会发现只有9090端⼝的实例收到了请求(同集群)

  2. 把9090端⼝的实例进⾏下线(SH集群), 再次访问接⼝, 观察⽇志, 发现9091端⼝和9092端⼝的实例收到了请求