3.接入Nacos注册中心以及Feign的使用

133 阅读3分钟

3.1 Nacos介绍

Nacos注册中心的主要功能:

  1. 存储注册上来的服务实例
  2. 返回服务实例给消费端
  3. 服务实例变更之后推送新的实例列表给消费端

3.2 服务注册获取实战

3.2.1 搭建Nacos

下载地址: github.com/alibaba/nac…

我们下载的是nacos-server-1.4.1.zip版本,然后解压缩。

# 解压缩
unzip nacos-server-1.4.1.zip
# 进入目录
cd nacos/bin 
# 启动
bin/startup.sh -m standalone

看到success等表明启动成功。

nacos启动成功.png

然后我们访问nacos,http://192.168.56.200:8848/nacos

当然这个nacos是单机版,生产环境我们需要安装集群版,参考官网集群版安装,这里不再详述。

3.2.2 将设备服务注册到Nacos

  1. 添加nacos依赖

<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

  1. 启动类上添加@EnableDiscoveryClient注解


@SpringBootApplication
@EnableDiscoveryClient
public class DeviceApplication {
    public static void main(String[] args) {
        SpringApplication.run(DeviceApplication.class, args);
    }
}
  1. 配置文件添加nacos地址
spring:
  application:
    name: smart-device
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.56.200:3306/device?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: password
  
  # nacos地址
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.56.200:8848

启动device服务,我们在nacos控制台看到device服务已经注册到nacos了。

device服务注册到nacos.png

3.2.3 将业务服务注册到Nacos

同理将业务服务注册到nacos,流程跟device服务注册类似,不再详述。

我们使用discoveryClient来从nacos注册中心中获取device服务实例,然后来调用设备服务获取设备信息。

/**
 * @description:
 * @author:xg
 * @date: 2024/12/8
 * @Copyright:
 */
@RestController
@RequestMapping("/deviceData")
@Slf4j
public class DeviceDataController {

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private DeviceDataService deviceDataService;

    @Resource
    private DiscoveryClient discoveryClient;

    @PostMapping("/save")
    public Boolean save(@RequestBody @Valid DeviceDataDTO deviceDataDTO) {

        // 通过discoveryClient从nacos中获取device服务实例
        ServiceInstance serviceInstance = discoveryClient.getInstances("smart-device").get(0);
        String url = serviceInstance.getHost() + ":" + serviceInstance.getPort();


        // 通过RestTemplate调用device服务获取设备绑定的userId
        DeviceVO deviceVO = restTemplate.getForObject(
                "http://"+url+"/device/get/" + deviceDataDTO.getPhysicalAdd(),
                DeviceVO.class);
        log.info("设备信息:{}", JSON.toJSONString(deviceVO));
        if(Objects.isNull(deviceVO)) {
            log.error("设备信息为null");
            return false;
        }
        // 存储设备数据到DB
        deviceDataDTO.setUserId(deviceVO.getUserId());
        deviceDataService.save(deviceDataDTO);
        return true;
    }
}

3.3 Feign的使用

Feign支持以接口service的形式便于更方便的调用服务,同时也集成了Ribbon负载均衡的。Ribbon负载均衡机制,是客户端负载均衡,当从nacos注册中心中获取到服务实例列表之后,基于算法(默认是轮询)获取一个服务实例进行调用,以此来达到均衡调用服务实例的目的,同时使得服务具有可扩展性。

我们在idea中再启动一个device服务,设置端口为8081

再开启一个device服务实例.png

3.3.1 添加Feign依赖

在smart-business业务服务工程中添加Feign依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

3.3.2 启动类上加上Feign注解

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients //开启Feign
public class BusinessApplication {
    public static void main(String[] args) {
        SpringApplication.run(BusinessApplication.class, args);
    }
}

3.3.3 定义Feign接口来调用device服务

/**
 * @description: 定义一个Feign接口,用于调用device服务
 * @author:xg
 * @date: 2024/12/13
 * @Copyright:
 */
@FeignClient("smart-device")
public interface FeignDeviceService {

    /**
     * 定义接口url、参数
     * @param physicalAdd
     * @return
     */
    @GetMapping("/device/get/{physicalAdd}")
    DeviceVO get(@PathVariable("physicalAdd") String physicalAdd);
}

3.3.4 修改controller使用Feign调用服务

/**
 * @description:
 * @author:xg
 * @date: 2024/12/8
 * @Copyright:
 */
@RestController
@RequestMapping("/deviceData")
@Slf4j
public class DeviceDataController {

    @Resource
    private DeviceDataService deviceDataService;

    
    @Resource
    private FeignDeviceService feignDeviceService;

    @PostMapping("/save")
    public Boolean save(@RequestBody @Valid DeviceDataDTO deviceDataDTO) {

        DeviceVO deviceVO = feignDeviceService.get(deviceDataDTO.getPhysicalAdd());
        
        log.info("设备信息:{}", JSON.toJSONString(deviceVO));
        if(Objects.isNull(deviceVO)) {
            log.error("设备信息为null");
            return false;
        }
        // 存储设备数据到DB
        deviceDataDTO.setUserId(deviceVO.getUserId());
        deviceDataService.save(deviceDataDTO);
        return true;
    }