目录
一. 基础介绍
- Feign 与 OpenFeign 的区别, Feign 停止更新后,SpringCloud 在 Feign 基础上进行增强推出的 Rest Client 服务消费端进行服务调用
- 在前面 SpringCloud 是通过 Ribbon+Remplate 调用服务接口,当一个服务接口需要被其它服务调用时需要进行正对性的封装,Feign 在此基础做了进一步的封装,只需要创建一个接口,进行一定配置,即可完成,简化了多于操作
- Fing 集成了 Ribbon 维护了服务列表信息,可以实现负载均衡,并且
二. 使用 OpenFeign 调用服务接口的实现步骤
- 服务提供方中存在提供服务的接口,并将服务以指定名称注册到了注册中心(此处以Eureka作为注册中心)
- 服务消费方创建专门使用 Feign 调用服务消费方的接口,接口使用 @FeignClient(value = “被调用的服务名称”),通过注解的value属性值指定当前 Feign 调用的是哪个服务提供方,底层会通过该值在注册中心获取该服务的调用列表,Feign 底层使用 Ribbon 然后本地负载,选择指定的服务 ip
- 接口中编写与要调用的服务提供方接口的对应接口(一一对应),并将接口注入到容器中
- 服务消费方启动类添加 @EnableFeignClients 修饰,表示开启 Feign 客户端调用功能
- 服务消费方 yml 文件配置调用服务接口超时时间,配置 Feign 日志记录功能等
服务提供方提供服务接口
服务提供方
- 服务提供方 yml ,配置注册中心,配置向注册中心注册的名字"cloud-payment-service"等等
server:
port: 8001 #当前服务端口号
spring:
application:
name: cloud-payment-service #当前服务名称
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: com.mysql.cj.jdbc.Driver #mysql驱动包
url: jdbc:mysql://localhost:3306/test01?serverTimezone=GMT%2B8 #连接的库
username: root
password:
#=================eureka相关配置======================
eureka:
client:
register-with-eureka: true #true 表示将当前服务注册到eureka注册中心
#true 表示是否在注册中心抓取已有的注册信息,集群环境时必须为true,配合ribbon进行负载
fetchRegistry: true
service-url:
#eureka 注册中心访问连接,集群环境多个注册地址
defaultZone: http://127.0.0.1:7001/eureka,http://127.0.0.1:7002/eureka
instance:
instance-id: payment8001 #配置当前服务向eureka注册中心注册时显示的服务器主机名称
prefer-ip-address: true #配置在开发人员直接访问eureka服务器时显示当前eureka上注册的服务的ip
lease-renewal-interval-in-seconds: 1 #指定定时向eureka注册中心发送代表当前服务心跳包的时间默认30秒
# Eureka 接收到当前服务最后一次发送代表正常心跳包的等待时间,超过则将当前服务在 Eureka 上踢除
lease-expiration-duration-in-seconds: 2
#=================eureka相关配置end======================
mybatis:
mapperLocations: classpath:mapper/*.xml #扫描mappper.xml */
type-aliases-package: com.test.dao #扫描对应mapper.xml 接口
- 服务提供方提供服务的接口
@Controller
public class PaymentController {
@RequestMapping(value = "/getAll", method = RequestMethod.GET)
@ResponseBody
public JsonResult getAll(){
System.out.println("微服务8001执行");
return paymentServerApi.getAll();
}
@RequestMapping(value = "/save", method = RequestMethod.GET)
@ResponseBody
public JsonResult saveOrUpdatePayment(){
System.out.println("微服务8001执行");
Payment payment = PaymentController.returnPayment();
return paymentServerApi.saveOrUpdatePayment(payment);
}
public static Payment returnPayment() {
Payment payment = new Payment();
//payment.setId();
payment.setSerialNumber("1111");
return payment ;
}
}
服务消费方
- pom 引入除了Spring , Eureka 依赖以外增加 Feign 依赖
<!-- openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
- 服务消费方创建 Feign 调用服务的接口,将接口注入到容器中
import com.common.result.JsonResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Component
//表示当前接口调用名为 "CLOUD-PAYMENT-SERVICE" 的服务提供方
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {
//与服务提供方中的接口一一对应,调用服务提供方中接口路径是"/save"的服务方法
//方法名返回值也要一一对应
@RequestMapping(value = "/save", method = RequestMethod.GET)
public JsonResult saveOrUpdatePayment();
//调用服务提供方接口路径是"/getAll"的服务方法
@RequestMapping(value = "/getAll", method = RequestMethod.GET)
public JsonResult getAll();
}
- 服务消费方通过接口调用服务,获取创建的 Feign 接口,调用接口中的方法, Controller 调用示例
import com.common.result.JsonResult;
import com.order.feignService.PaymentFeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class OrderController {
//自己创建注入到容器中的 Feign 服务调用接口
@Autowired
private PaymentFeignService paymentFeignService;
@RequestMapping(value = "/consumer/feign/save", method = RequestMethod.GET)
@ResponseBody
public JsonResult save(){
//通过 paymentFeignService 调用方
return paymentFeignService.saveOrUpdatePayment();
}
@RequestMapping(value = "/consumer/feign/getAll", method = RequestMethod.GET)
@ResponseBody
public JsonResult getAll(){
return paymentFeignService.getAll();
}
}
- 启动类增加 @EnableFeignClients 开启 feign 调用功能
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients //开启 feign 调用功能
public class OrderFeignMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderFeignMain80.class,args);
}
}
OpenFeign 调用服务超时问题
在使用 Feign 调用服务接口时,默认等待1秒,如果一秒没有拿到被调用服务返回的请求结果会自动报错,在实际开发中,一个逻辑接口调用可能会超过1秒,可以在服务消费方的 yml 配置文件中,使用 Ribbon 配置(Feign 底层通过 Ribbon 进行负载)
OpenFeign 日志打印功能
- Feign 提供了日志打印功能,可以通过配置调整日志级别,可以通过Feign获取发送请求的细节
- Feign支持的日志级别:
NONE: 默认的,不显示任何日志
BASIC: 仅记录请求方法,URL,响应状态码,执行时间
HEADERS: 除了 BASIC 中的信息以外,还包含请求和响应的头信息
FULL: 除了 HEADERS 中的信息以外,还包含请求和响应的正文及元数据
- 实现步骤:
1.服务消费方在项目中创建配置类,配置 Feign 支持的日志级别,注入到 Spring 容器中
2.服务消费方在 yml 文件中配置 Feign 日志监控哪个接口(当前项目中使用Feign调用其它服务的 Feign 接口)
- 配置类示例:
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
//此处以 FULL 级别为例
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}
- 在 yml 中配置 Feign 监控记录日志的接口后,调用被监控的方法执行记录日志示例
服务消费方 yml 中配置 Feign 调用超时与 Feign 日志
server:
port: 80 #当前服务端口号
spring:
application:
name: cloud-feign-order-service #当前服务名称
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
#eureka 注册中心访问连接,集群环境多个注册地址
defaultZone: http://127.0.0.1:7001/eureka,http://127.0.0.1:7002/eureka
instance:
instance-id: order80 #配置当前服务向eureka注册中心注册时显示的服务器主机名称
prefer-ip-address: true #配置在开发人员直接访问eureka服务器时显示当前eureka上注册的服务的ip
lease-renewal-interval-in-seconds: 1 #指定定时向eureka注册中心发送代表当前服务心跳包的时间默认30秒
lease-expiration-duration-in-seconds: 2 # Eureka 接收到当前服务最后一次发送代表正常心跳包的等待时间,超过则将当前服务在 Eureka 上踢除
#=====================Feign===========================================
#超时时间配置
ribbon:
ReadTimeout: 5000 #当前服务消费方调用服务提供方,建立连接超时时间,默认1秒超过报错
ConnectTimeout: 5000 #当前服务消费方与服务提供方建立连接后调用服务接口读取资源的时间
#配置 Feign 日志功能
logging:
level:
#表示 com.order.feignService.PaymentFeignService 接口中的方法执行,被 Feign 监控,记录日志
com.order.feignService.PaymentFeignService: debug
#=====================Feign end===========================================