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,会发现控制台的输出内容如下图所示。

Comments | NOTHING