首页 > 其他分享 >Feign

Feign

时间:2023-06-20 19:13:34浏览次数:26  
标签:Feign HTTP 请求 压缩 gzip 客户端

1.概念

Feign是Spring Cloud Netflix组件中的一个轻量级RESTful的HTTP服务客户端,实现了负载均衡和Rest调用的开源框架
封装了Ribbon和RestTemplate,实现了WebService的面向接口编程,进一步降低了项目的耦合度。
Feign内置了Ribbon,用来做客户端负载均衡调用服务注册中心的服务。
Felgn本身并不支持Spring MVC的注解,它有一会自己的注解,为了更方便的使用,Spring Cloud孵化了openFelgn。
Feign是一种声明式、模板化的HTTP客户端(仅在Consumer中使用)。
Feign支持的注解和用法请参考官方文档: htps://github.com/OpenFeign/feign 或spring.io言网文档
Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务。
Feign旨在使编写JAVA HTTP客户端变得更加容易,Feign 简化了RestTemplate代码,实现了Ribbon负载均衡
使代码变得更加简洁,也少了客户端调用的代码,使用Feign实现负载均衡是首选方案。
只需要你创建一个接口,然后在上面添加注解即可。
Feign是声明式服务调用组件,其核心就是:像调用本地方法一样调用远程方法,无感知远程HTTP请求。

  • 它解决了让开发者调用远程接口就跟调用本地方法一样的体验,开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求。无需关注与远程的交互细节,更无需关注分布式环境开发。
  • 它像Dubbo-样, Consumer直接调用Provider接口方法,而不需要通过常规的Http Client构造请求再解析返回数据。
    OpenFeign是Spring Cloud在Feign的基础上支持了Spring MVC的注解,如@RequesMapping 、Pathvariable 等等。
    OpenFeign的@FeignClient 可以解析SpringMVC的@RequestMapping 注解下的接口,并通过动态代理的方式产“生实现
    类,实现类中做负载均衡并调用服务。
  • 读作 fei en

2.实现

  • 服务中心和提供者一致
  • pom.xml
<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
  • 生产者中的ProductService
@FeignClient("provider")
public interface ProductService {
    @GetMapping("/product/list")
    List<Product> listProducts();
}

3.Feign负载均衡

Feign封装了Ribbon自然也就集成了负载均衡的功能,默认采用轮询策略。如何修改负载均衡策略呢?与之前学习Ribbon时讲解的配置是一致的。

4.参数请求

  • 消费者的ProductSercice
@FeignClient("provider")
public interface ProductService {

    @GetMapping("/product/{id}")
    Product selectProductById(@PathVariable("id") Integer id);

    @PostMapping("/product/save")
    Map<Object, Object> createProduct(Product product);
}
  • 生产者的ProductController
@RestController
@RequestMapping("/product")
public class ProductController {
    @Autowired
    private ProductService productService;

    @GetMapping("/{id}")
    public Product selectProduct(@PathVariable("id") Integer id){
        return productService.selectProductById(id);
    }

    @PostMapping("/save")
    public Map<Object, Object> createProduct(@RequestBody Product product){
        return productService.createProduct(product);
    }
}

5.Feign性能优化

5.1 Gzip压缩

gzip介绍: gzip 是-种数据格式,采用deflate 算法压缩数据; gzip 是-种流行的文件压缩算法,应用十分广泛,尤其是在Linux平台。
gzip能力:当Gzip压缩一个纯文本文件时,效果是非常明显的,大约可以减少70%以上的文件大小。
gzip作用:网络数据经过压缩后实际上降低了网络传输的字节数,最明显的好处就是可以加快网页加载的速度。
网页加载速度加快的好处不言而喻,除了节省流量,改善用户的浏览体验外,另一个潜在的好处是Gzip与搜索引擎的抓取工具有着更好的关系。
例如Google就可以通过直接读取gzip文件来比普通手工抓取更快地检索网页。

5.1.1 HTTP协议关于压缩传输的规定

1.客户端向服务器请求中带有: Accept-Encoding:gzip ,deflate 字段,向服务器春示賽户端支持的压缩格式(gzip 或
者deflate),如果不发送该消息头,服务端默认是不会压缩的。
2.服务端在收到请求之后,如果发现请求头中含有Accept-Encoding 字段,并且支持该类型压缩,就会对响应报文压缩之
后返回给客户端,并且携芾Content- Encoding:gzip消息头,表示响应报文是根据该格式进行压缩的。
3.客户端接收到请求之后,先判断是否有Content-Encoding 消息头,如果有,按该格式解压报文。否则按正常报文处理。

5.1.2 实现
  • 局部
    只配置Consumer通过Feign到Provider的请求与相应的Gzip压缩。服务消费者application.yml
server:
  port: 9090
  compression:
    #开启压缩
    enabled: true
    #压缩支持的 MINME TYPE
    mime-types: application/json,application/xml,text/html,text/xml,text/plain
  • 全局
    对客户端浏览器的请求以及Consumer对Provider的请求与响应都实现Gzip压缩。
    服务消费者applicationyml
feign:
  compression:
    request:
      mime-types: text/xml. application/xn1. application/json #配置压缩支持的MIME TYPE
      min-request-size: 512 #配置压缩数据大小的最小阈值,默认2048
      enabled: true #请求是否开启gzip压缩
    response:
      enabled: true #响应是否开启gzip压缩

5.2 HTTP连接池

5.2.1HTTP的背景原理

  • 两台服务器建立HTTP连接的过程是很复杂的一个过程,涉及到多个数据包的交换,很耗时间。
  • HTTP连接需要的3次握手4次挥手开销很大,这一 开销对于大量的比较小的HTTP消息来说更大。

5.2.2 解决方案

采用HTTP连接池,可以节约大量的3次握手4次挥手,这样能大大提升吞吐量。
Feign的HTTP客户端支持3种框架: HttpURLConnection,HttpClient,OkHttp;默认是HttpURLConnection 。

  • 传统的HttpURLConnection是JDK自带的,并不支持连接池,如果要实现连接池的机制,还需要自己来管理连接对象。
    对于网络请求这种底层相对复杂的操作,如果有可用的其他方案,没有必要自己去管理连接对象。
  • HttpClient 相比传统JDK自带的HttpURLConnection,它封装了访问HTTP的请求头,参数,内容体,响应等等
    它不仅使客户端发送HTTP请求变得容易,而且也方便了开发人员测试接口(基于HTTP协议的) , 既提高了开发的效率,又提高了代码的健壮性;
    另外高并发大量的请求网络的时候,也是用连接池提升吞吐量。

5.2.3 实现

#httpclient开启
feign:
  httpclient:
    enabled: true

5.3 状态查看

浏览器发起的请求我们可以借助F12 Devtools 中的Network来查看请求和响应信息。
对于微服务中每个接口我们又该如何查看URL,状态码和耗时信息?我们可以使用配置日志的方式进行查看。

5.3.1 实现

  • logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">

    <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
    <property name="LOG_HOME" value="/home" />

    <!--控制台日志, 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度,%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>

    <!--文件日志, 按照每天生成日志文件 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

    <!-- show parameters for hibernate sql 专为 Hibernate 定制 -->
    <logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE" />
    <logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="DEBUG" />
    <logger name="org.hibernate.SQL" level="DEBUG" />
    <logger name="org.hibernate.engine.QueryParameters" level="DEBUG" />
    <logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG" />

    <!--myibatis log configure-->
    <logger name="com.apache.ibatis" level="TRACE"/>
    <logger name="java.sql.Connection" level="DEBUG"/>
    <logger name="java.sql.Statement" level="DEBUG"/>
    <logger name="java.sql.PreparedStatement" level="DEBUG"/>

    <!-- 日志输出级别 -->
    <root level="DEBUG">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="FILE"/>
    </root>
</configuration>
  • 启动类加入
/**
     * NONE: 不记录任何信息
     * BASIC 记录请求方法,URL,状态码,用时
     * HEADERS BASIC基础上记录一些常用信息
     * FULL 记录请求相关所有信息
     * @return
     */
    @Bean
    public Logger.Level getLog(){
        return Logger.Level.FULL;
    }
  • application.yml
#httpclient开启
feign:
  httpclient:
    enabled: true
  client:
    #服务名称
    provider:
      loggerLevel: FULL

5.4 请求超时

Feign的负载均衡底层用的就是Ribbon,所以这里的请求超时配置其实就是配置Ribbon.
分布式项目中,服务压力比较大的情况下,可能处理服务的过程需要花费一定的时间, 而默认情况下请求超时的配置是1s所以我们需要调整该配置延长请求超时时间。

5.4.1 实现

  • 局部
provider:
  ribbon:
    NFLoadBalanceRuleClassName: com.netflix.loadbalancer.RandomRule
    #所有请求都进行重试
    OkToRetryOnAllOperations: true
    #对当前实例重试次数
    MaxAutoRetries: 2
    #切换实例的重试次数
    MaxAutoRetriesNextServer: 0
    #请求连接的超时时间
    ConnectTimeout: 3000
    #请求处理的超时时间
    ReadTimeout: 3000
  • 全局
ribbon:
  #请求连接超时时间
  ConnectTimeout: 5000
  #请求处理的超时时间
  ReadTimeout: 5000

标签:Feign,HTTP,请求,压缩,gzip,客户端
From: https://www.cnblogs.com/lwx11111/p/17494451.html

相关文章

  • feign携带用户信息
    1.通过feignConfig配置文件来携带用户信息。2.@FeignClient(name="user-server",configuration={FeignConfig.class})3.feignConfig是实现了请求拦截器的,他可以把用户信息放到requestTemplate中。在header里面放一个key(user-info),value是用户信息。4.服务端,feign实现了......
  • springboot-feign接口压缩异常
    WARNorg.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver-Resolved[org.springframework.http.converter.HttpMessageNotReadableException:JSONparseerror:Illegalcharacter((CTRL-CHAR,code31)):onlyregularwhitespace(\r,\......
  • 真实案例:Feign 切换 okhttp 无法生效,被老大骂的有点慌!
    来源:https://www.cnblogs.com/mufeng3421/p/11442412.html提示:如果只看如何解决问题,请看文章的末尾如何解决这个问题1.场景描述最近项目中使用了feign当做http请求工具来使用、相对于httpclient、resttemplate来说,fegin用起来方便很多。然后项目有httptrace的需求,需要输出请求......
  • com.netflix.hystrix.exception.HystrixRuntimeException: xxxFeign#xxxx timed-out a
    问题描述在使用Feign进行远程调用时遇到的bug。原因是因为超时了。需要对超时时间进行设置一下即可。在Nacos进行设置原先的contentTimeout和readTimeout都是2000,修改成20000后bug便解决了。......
  • springboot - feign.FeignException$BadRequest: [400] during [GET] to [http:
    ERROR失败原因:、feign.FeignException$BadRequest:[400]during[GET]to[http://方法?携带的请求头条件。。。。。[ManualStockControllerFeign#deleteManualStockTaskByIds(List)]:<!doctypehtml><htmllang="en"><head><title>HTTPStatus400–Bad......
  • 微服务之间的调用方式RestTemplate和FeignClient
    SpringCloud服务间的调用有两种方式:RestTemplate和FeignClient。不管是什么方式,他都是通过REST接口调用服务的http接口,参数和结果默认都是通过jackson序列化和反序列化。因为SpringMVC的RestController定义的接口,返回的数据都是通过Jackson序列化成JSON数据。一、RestTemplate使用......
  • spring cloud 之 openfeign 记录(通过feign上传)
    今日搭建好nacos nacos踩坑记录迫不及待的进入了下一步,服务间的远程调用,就踩了一个小小的坑 我做的是一个阿里oss上传的服务!阿里oss服务个人可以有三个月试用,对新手非常的友好首先是一个openfeign编写上的问题@RequestMapping(value="/common/oss/download",meth......
  • Feign使用实践
    Feign是一个声明式的HTTP客户端,用于简化微服务架构中的服务调用。它基于注解和接口定义,可以与服务发现组件(例如Eureka)和负载均衡组件(例如Ribbon)集成,提供了更简洁、可读性更高的代码来实现服务间的通信。下面是使用Java代码实现Feign入门示例的详细步骤:添加依赖项:在您的Java......
  • 4.OpenFeign
    5.OpenFeignOpenFeign主要基于接口和注解实现了远程调用5.1.简介官网:https://docs.spring.io/spring-cloud-openfeign/docs/2.2.4.RELEASE/reference/html/#spring-cloud-feignFeign是声明性(注解)Web服务客户端。它使编写Web服务客户端更加容易。要使用Feign,先创建一个接......
  • OpenFeign
    OpenFeign简介Feign是一个声明式的WebService客户端,是一种声明式、模板化的HTTP客户端。OpenFeign是SpringCloud在Feign的基础上支持了SpringMVC的注解,如@RequesMapping等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产......