likes
comments
collection
share

springboot集成nacos服务注册发现中心

作者站长头像
站长
· 阅读数 15

之前我们谈了springboot集成nacos配置中心的功能使用,用起来确实很简单。本篇我们要谈下如何在springboot中使用nacos另一项重大的功能:服务注册和发现。

本篇我们以springboot 2.7.0版本为例讲解集成nacos服务注册和发现中心的功能。

1、修改pom文件

修改springboot应用的pom文件,添加如下依赖:

       <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>nacos-discovery-spring-boot-starter</artifactId>
            <version>0.2.11</version>
        </dependency>

2、修改application.yml文件

修改springboot应用resources目录下的application.yml(或yaml或properties)文件,新增nacos服务注册相关配置:

server:
  port: 8080
  servlet:
    context-path: /nacos


spring:
  application:
    name: springboot-nacos

# nacos相关配置
nacos:
  discovery:
    server-addr: 127.0.0.1:8848
    #是否将本应用注册到nacos服务列表,默认是false
    auto-register: true
    #本服务所属的命名空间的ID,默认是空,也就是public
    namespace: c91a7f69-cefc-4ee3-8350-07ab87affd05
    register:
      #本服务是否接受外部的请求,默认true
      enabled: true
      #本服务要注册到命名空间下的哪个组,默认DEFAULT_GROUP
      group-name: DEFAULT_GROUP
      #服务的名称,会展示在nacos服务列表,要求唯一,可以不写,默认是spring.application.name的值
      service-name: 

我们简单说下上面的配置。

2.1、auto-register配置

auto-register配置表示我们的应用要不要作为一项服务注册到nacos服务列表,默认是false。如果我们引入nacos-discovery,只是为了从nacos上面获取别的服务的信息而不想暴露自己的服务,则使用默认值false或者直接忽略这一项即可。如果我们写为true,那么我们系统在启动完成后,nacos客户端就会把我们当前系统的服务名(默认是spring.application.name的值)、所在服务器的ip和端口信息注册到nacos服务列表。

2.2、namespace配置

namespace配置项用来表明我们要把当前的服务注册到哪个命名空间下面。咱们之前学nacos的时候,nacos会按照"namespace->group->dataId"的方式来将配置信息进行隔离,对于nacos服务列表也是一样的处理逻辑:我们依旧可以将namespace作为环境标识来使用,然后把我们的服务注册到该命名空间下,确保不同环境的应用不会跨环境调用到其他环境的应用。

2.3、register配置

register配置用来表示我们服务注册的具体行为。比如group_name指我们要把服务注册到服务列表的(指定命名空间的)哪个组下面。如果我们配置了2.2部分的namespace,那么此处的group_name就指在该namespace下面的组,我们当前应用的信息就在这个组下面。另外enabled属性代表我们的应用是否愿意接受外部的请求。我们把自己的应用服务注册到Nacos,是为了方便其他应用能根据服务名找到我们应用所在的服务器信息,我们可以控制我们的服务要不要被别的应用调用。虽然我们把服务注册上去了,但是其他应用在获取服务列表时,如果nacos客户端发现某一个服务实例的enabled为false,就不会请求这个实例,会再去判断该服务下面的其他服务实例(集群内其他机器)。

3、编写代码验证

我们在controller层新增一个接口如下:

package com.xk.nacos.springboot.controller;

import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author xk
 * @since 2023.05.29 20:37
 */
@RestController
public class NacosDiscoveryControlller {
    
    @NacosInjected
    private NamingService namingService;
    
    /**
     * 根据服务名称获取服务的所有(机器)实例信息
     * @param serviceName 服务名称
     * @return
     * @throws NacosException
     */
    @GetMapping("getInstances")
    public List<Instance> getInstances(String serviceName) throws NacosException {
        return namingService.getAllInstances(serviceName);
    }
}

访问getInstances接口,接口参数serviceName取我们当前应用的名称(spring.application.name的值),可得到如下结果:

springboot集成nacos服务注册发现中心

上面的接口返回的内容就是我们当前应用的所有实例信息,假如我们在多台服务器上部署了我们的这个应用,那么这几台服务器的信息就都能通过该接口返回过来。

4、查看nacos控制台服务列表

我们通过浏览器登录nacos控制台,查看nacos服务列表可以看到如下内容:

springboot集成nacos服务注册发现中心

列表里的数据就是我们的应用信息,服务名是我们应用里面spring.application.name的值。

我们点击操作栏的“详情”,有如下内容:

springboot集成nacos服务注册发现中心

nacos默认一个服务下面对应着一个集群,而服务详情的页面就展示了该集群下面所有的服务实例信息,比如服务所在的服务器ip、监听的端口等信息。如果我们调用别人的http服务,在知道了接口路径之后,只要知道服务所在的服务器ip和端口号,就能发起调用。

5、注册上去的服务到底有啥用

前面说了怎么把服务注册到nacos上面,但是注册上去之后,到底有啥用呢?或者说怎么去调用这个服务呢?本部分就简单说下这块,其实也就是服务的发现过程。

我们在之前的controller中添加如下的代码:

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 通过服务名获取指定ID的用户信息
     * @param id
     * @return
     * @throws NacosException
     */
    @GetMapping("queryUserInfo")
    public String queryUserInfo(String id) throws NacosException {
        String path = "/api/user?id="+id;
        //另一个应用的名称,并且已注册到nacos服务列表
        String serviceName = "portal";
        String url = "";
        List<Instance> instances = getInstances(serviceName);
        if(instances == null || instances.size() == 0){
            //可以抛出未找到服务信息的异常
            return null;
        }
        //获取第一个服务实例,当然也可以通过某种算法获取别的实例信息,比如随机算法,类似于在此处做客户端负载均衡
        Instance instance = instances.get(0);
        url = "http://"+instance.getIp()+":"+instance.getPort()+path;
        return restTemplate.getForObject(url,String.class);
    }

其中要先将restTemplate对象通过@Bean的方式注入到spring容器中。

@Configuration
public class BeanConfig {

    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

上面的接口就是简单演示了下如何根据服务名称调用目前目标服务的接口。其实思路很简单,就是先根据服务名称去nacos上面查询这个服务下面所有的服务实例信息,然后可以根据某种算法选择一个实例,读取实例中的ip和port信息,再组装成最终的url地址信息,发起http调用。

当然,springboot集成nacos服务注册和发现中心的功能用起来似乎没有那么的方便,但是我们可以根据nacos官方已有的功能进行拓展,比如我们可以提供一个sdk包,就像上面写的接口那样,用户只需要通过服务名就能直接调用目标服务,假如用户要调用的url地址是这样的:

http://portal/api/user?id=1

我们可以在sdk包自动解析portal所对应的服务实例信息,然后帮用户完成调用。

结束语

觉得有收获的朋友,可以点击关注我,这样方便接收我后续的文章,多谢支持~