暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

springcloud feign

李二狗搞程序 2021-08-06
335

Feign可以做到使用 HTTP 请求远程服务时就像调用本地方法一样的体验,开发者完全感知不到这是远程方法,更感知不到这是个 HTTP 请求。它像 Dubbo 一样,consumer 直接调用接口方法调用 provider,而不需要通过常规的 Http Client 构造请求再解析返回数据。它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细节,更无需关注分布式环境开发。

添加feign 的依赖


<!-- 引入open feign 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

使用,在接口上添加注解 @FeignClient("") 进行配置

@FeignClient(value = "order-server", path = "order")
public interface OrderFeignService {
@GetMapping("/findOrderByUserId/{id}")
R findOrderByUserId(@PathVariable("id") Integer id);
}

在启动类中加入注解 @EnableFeignClients

@SpringBootApplication
@EnableFeignClients
public class StudyuserApplication {


public static void main(String[] args) {
SpringApplication.run(StudyuserApplication.class, args);
}


}

在UserController 调用 , 跟普通接口一样的写法。

@Autowired
private OrderFeignService orderFeignService;


@GetMapping("/findOrderByUserIdWithFeign/{id}")
public R findOrderByUserIdWithFeign(@PathVariable("id") Integer id) {
// feign调用
R result = orderFeignService.findOrderByUserId(id);
return result;
}

测试,验证

spring cloud feign 的自定义配置及使用

日志配置

有时候我们遇到 Bug,比如接口调用失败、参数没收到等问题,或者想看看调用性能,就需要配置 Feign 的日志了,以此让 Feign 把请求信息输出来。

日志等级有 4 种,分别是:

NONE【性能最佳,适用于生产】:不记录任何日志(默认值)。

BASIC【适用于生产环境追踪问题】:仅记录请求方法、URL、响应状态代码以及执行时间。

HEADERS:记录BASIC级别的基础上,记录请求和响应的header。

FULL【比较适用于开发及测试环境定位问题】:记录请求和响应的header、body和元数据

全局配置

加入配置类 FeignConfig

package com.jiuge.user.config;


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


/**
* @author jiuge
* @version 1.0
* @date 2021/8/5 11:16
*/
@Configuration
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}

配置好后在yml 文件加入对应feign目录的日志级别

logging:
level:
com.jiuge.user.feign: debug

请求接口 http://localhost:8010/user/findOrderByUserIdWithFeign/1 测试,验证, 把日志请求信息打印出来了

2021-08-05 11:22:08.205 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService   : [OrderFeignService#findOrderByUserId] ---> GET http://order-server/order/findOrderByUserId/1 HTTP/1.1
2021-08-05 11:22:08.205 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] ---> END HTTP (0-byte body)
2021-08-05 11:22:08.562 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] <--- HTTP/1.1 200 (356ms)
2021-08-05 11:22:08.562 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] connection: keep-alive
2021-08-05 11:22:08.563 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] content-type: application/json
2021-08-05 11:22:08.563 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] date: Thu, 05 Aug 2021 03:22:08 GMT
2021-08-05 11:22:08.563 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] keep-alive: timeout=60
2021-08-05 11:22:08.563 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] transfer-encoding: chunked
2021-08-05 11:22:08.563 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId]
2021-08-05 11:22:08.563 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] {"msg":"success","code":0,"orders":[{"id":1,"userId":"1","commodityCode":"UT2191929213903","count":1,"amount":2}]}
2021-08-05 11:22:08.563 DEBUG 14128 --- [nio-8010-exec-1] com.jiuge.user.feign.OrderFeignService : [OrderFeignService#findOrderByUserId] <--- END HTTP (114-byte body)


局部配置  去除FeignConfig 上的Configuration 注解

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

修改OrderFeignService 接口的注解,接口头加入 configuration 注解

// feignConfig 的局部配置
@FeignClient(value = "order-server", path = "order",configuration = FeignConfig.class)
public interface OrderFeignService {
@RequestMapping("/findOrderByUserId/{id}")
R findOrderByUserId(@PathVariable("id") Integer id);
}

请求接口http://localhost:8010/user/findOrderByUserIdWithFeign/1测试,验证

局部配置2,可以在yml 进行配置

logging:
level:
com.jiuge.user.feign: debug
feign:
client:
config:
order-server:
loggerLevel: FULL

OrderFeignService 类上去除  configuration  配置

@FeignClient(value = "order-server", path = "order",configuration = FeignConfig.class)

换成

@FeignClient(value = "order-server", path = "order")

测试验证

契约配置

Spring Cloud 在 Feign 的基础上做了扩展,可以让 Feign 支持 Spring MVC 的注解来调用。原生的 Feign 是不支持 Spring MVC 注解的,如果你想在 Spring Cloud 中使用原生的注解方式来定义客户端也是可以的,通过配置契约来改变这个配置,Spring Cloud 中默认的是 SpringMvcContract。


修改契约配置,支持原生的配置

在FeignConfig 上添加如下内容


/**
* 修改契约配置,支持Feign原生的注解
* @return
*/
@Bean
public Contract feignContract() {
return new Contract.Default();
}

修改OrderFeignService 类内容

使用原生的feign 注解 @RequestLine

// feignConfig 的局部配置
@FeignClient(value = "order-server", path = "order")
public interface OrderFeignService {
// @RequestMapping("/findOrderByUserId/{id}")
@RequestLine("GET /findOrderByUserId/{userId}")
R findOrderByUserId(@PathVariable("userId") Integer userId);
}

局部配置  上面配置需要加这个

修改application.yml 文件  添加contract

feign:
client:
config:
order-server:
loggerLevel: FULL
contract: feign.Contract.Default #指定Feign原生注解契约配置

通过拦截器实现认证

通常我们调用的接口都是有权限控制的,很多时候可能认证的值是通过参数去传递的,还有就是通过请求头去传递认证信息,比如 Basic 认证方式。

添加bean 实例

@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor(){
return new BasicAuthRequestInterceptor("jiuge","123456");
}

扩展点  feign.RequestInterceptor

每次 feign 发起http调用之前,会去执行拦截器中的逻辑。

public interface RequestInterceptor {
/**
* Called for every request. Add data using methods on the supplied {@link}.
*/

void apply(RequestTemplate template);
}

使用场景

统一添加 header 信息;

对 body 中的信息做修改或替换;


自定义拦截实现逻辑

public class FeignAuthRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
// 业务逻辑
String access_token = UUID.randomUUID().toString();
template.header("Authorization",access_token);
}
}

order-server 端可以通过 @RequestHeader获取请求参数


全局配置

@Configuration  // 全局配置
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
/**
* 自定义拦截器
* @return
*/
@Bean
public FeignAuthRequestInterceptor feignAuthRequestInterceptor(){
return new FeignAuthRequestInterceptor();
}
}

局部配置

feign:
client:
config:
order-server:
loggerLevel: FULL
requestInterceptors[0]:
com.jiuge.user.interceptor.FeignAuthRequestInterceptor

超时时间配置

通过 Options 可以配置连接超时时间和读取超时时间,Options 的第一个参数是连接的超时时间(ms),默认值是 2s;第二个是请求处理的超时时间(ms),默认值是 5s。

@Bean
public Request.Options options() {
return new Request.Options(5000, 10000);
}


局部配置

feign:
client:
config:
order-server:
loggerLevel: FULL
# 连接超时时间,默认2s
connectTimeout: 2000
# 请求处理超时时间,默认5s
readTimeout: 3000

补充说明:Feign的底层用的是Ribbon,但超时时间以Feign配置为准


客户端组件配置

配置Apache HttpClient

引入依赖

<!-- Apache HttpClient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.7</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>10.1.0</version>
</dependency>


修改yml 文件 ,启用 apache httpclient

feign:
#feign 使用 Apache HttpClient 可以忽略,默认开启
httpclient:
enabled: true

测试,验证  会进入ApacheHttpClient 中的execute 方法


配置OkHttp

引入依赖


<!-- 引入OkHttp -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>



修改yml,将Feign的HttpClient 禁用, 启用OkHttp

feign:
#feign 使用 okhttp
okhttp:
enabled: true

测试,验证   会进入OkHttpClient 类的 execute 方法

GZIP 接口压缩配置

开启压缩可以有效节约网络资源,提升接口性能,可以配置GZIP 来压缩数据

修改yml 文件,为如下内容


feign:
httpclient:
enabled: true
compression:
request:
enabled: true
# 配置压缩的类型
mime-types: text/xml,application/xml,application/json
#最小压缩值
min-request-size: 2048
response:
enabled: true

注意:只有当Feign 的Http client 不是okhttp3的时候,压缩才会生效, 配置源码在 FeignAcceptGzipEncodingAutoConfiguration 上

测试,验证

编码器解码器配置

引入jackson 依赖

<!-- 引入jackson 依赖 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jackson</artifactId>
</dependency>

java 配置方式

@Bean
public Decoder decoder() {
return new JacksonDecoder();
}
@Bean
public Encoder encoder() {
return new JacksonEncoder();
}

yml 配置方式

feign:
client:
config:
order-server: #对应微服务
# 配置编解码器
encoder: feign.jackson.JacksonEncoder
decoder: feign.jackson.JacksonDecoder

以上两种,任选一种进行配置。

文章转载自李二狗搞程序,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论