SpringCloud 详解(七)

发布于 2022-04-17  108 次阅读


OpenFeign

Feign 是 SpringCloud 组件中的一个轻量级 RESTful 的 HTTP 服务客户端。Feign 内置了 Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。Feign 的使用方式是:使用 Feign 的注解定义接口,调用这个接口,就可以调用服务注册中心的服务。

OpenFeign 是 SpringCloud 在 Feign 的基础上支持了 SpringMVC 的注解,如 @RequesMapping。OpenFeign 的 @FeignClient 可以解析 SpringMVC 的 @RequestMapping 注解下的接口,并通过动态代理的方式产生实现类,在实现类中做负载均衡并调用其它服务。

服务调用

准备工作

创建一个 Module,一个空的 Maven 项目。并导入下面的依赖。

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>ml.guest997</groupId>
        <artifactId>Commons</artifactId>
        <version>${project.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

在 resources 文件夹下创建 application.yaml 配置文件,并加入下面的配置。

server:
  port: 80

spring:
  application:
    name: order

eureka:
  client:
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/, http://eureka7002.com:7002/eureka/

主启动类

package ml.guest997;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

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

Service 层

package ml.guest997.service;

import ml.guest997.pojo.CommonResult;
import ml.guest997.pojo.Payment;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;

@Component
@FeignClient("PAYMENT")
public interface PaymentService {
    @GetMapping("/payment/add")
    CommonResult add(Payment payment);      //跟支付模块 controller 中定义的方式一样,不需要自己写实现类,通过动态代理实现。
}

Controller 层

package ml.guest997.controller;

import lombok.extern.slf4j.Slf4j;
import ml.guest997.pojo.CommonResult;
import ml.guest997.pojo.Payment;
import ml.guest997.service.PaymentService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
@Slf4j
public class OrderController {
    @Resource
    private PaymentService paymentService;

    @GetMapping("/consumer/payment/add")
    public CommonResult add(Payment payment) {
        return paymentService.add(payment);
    }
}

测试

分别启动 Eureka-Server、Payment、Payment2 和 Order2 模块后,浏览器多次访问:127.0.0.1/consumer/payment/add?serial=Guest006,会发现端口是互相切换的,就说明 OpenFeign 内部已经实现了负载均衡。

超时控制

OpenFeign 调用远程服务时,一定时间内没有建立起请求或没有响应,就会报错。

添加支付 Controller

@GetMapping("/payment/timeout")
public String paymentTimeout() {
    try {
        TimeUnit.MINUTES.sleep(1);      //休眠1分钟
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return serverPort;
}

添加订单接口

@GetMapping("/payment/timeout")
String paymentTimeout();

添加订单 Controller

@GetMapping("/consumer/payment/timeout")
public String paymentFeignTimeout() {
    return paymentService.paymentTimeout();
}

测试

分别启动 Eureka-Server、Payment、Payment2 和 Order2 模块后,浏览器访问:127.0.0.1/consumer/payment/timeout,过了一段时间后就会发现页面报错了。

添加配置

feign:
  client:
    config:
      default:
        connectTimeout: 3000    #指的是建立连接所用的时间
        readTimeout: 80000      #指的是建立连接后收到响应所用的时间

日志增强

通过配置来调整日志级别,从而了解请求中的细节。

日志级别

  • NONE:默认的,不显示任何日志。
  • BASIC:仅记录请求方法、URL、响应状态码及执行时间。
  • HEADERS:除了 BASIC 中定义的信息之外,还有请求和响应的头信息。
  • FULL:除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据。

配置类

package ml.guest997.config;

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignConfig {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

添加配置

logging:
  level:
    ml.guest997.service.PaymentService: debug   #指定特定的接口的日志级别(会被上面的配置覆盖)

测试

分别启动 Eureka-Server、Payment、Payment2 和 Order2 模块后,浏览器访问:127.0.0.1/consumer/payment/add?serial=Guest007,会发现控制台的输出内容如下图所示。

SpringCloud 详解(七)插图