经验大分享:SpringCloud之Feign

简介: 经验大分享:SpringCloud之Feign

不忘初心,方得始终

目录

什么是feign ?1. 什么是声明式呢?2. 工作原理入门案例先看book-api的代码ch4-book-service的代码:ch4-book-consumer 的代码:传参数fegin 性能优化gzip压缩HTTP协议中关于压缩传输的规定:那我们使用fegin怎么做压缩呢? HTTP连接池优化为什么http连接池能提升性能?使用httpClient连接池 日志输出: Feign的优化配置先来看全局配置:局部配置

正文

资料来源: [重新定义Spring Cloud]以及博客和官网

源码地址:

回到顶部什么是feign ?

fegin是一种声明式 模板化的HTTP客户端(仅在consumer中使用)

1. 什么是声明式呢?

声明式调用就像调用本地方法一样调用远程方法,无感知远程http请求

Spring Cloud的声明式调用,可以做到使用HTTP请求远程服务时就像调用本地方法一样的体验,开发者完全感知不到这是远程调用,更加不知道这是一个http请求

像dubbo一样,consumer直接调用接口方法调用provider,而不需要通过常规的httpclient构造在解析返回数据

解决了.开发者调用远程和调用本地一样,无需关心远程交互的细节,更无需关注分布式环境

2. 工作原理

在开发微服务应用时,我们会在主程序入口添加@EnableFeignClients注解开启对FeginClient扫描加载处理,

当程序启动时,会进行扫描,扫描所有@FeginClients的注解类,并将这些信息,注入到Spring IOC容器中. 当定义的fegin接口中的方法被调用时,通过JDK代理的方式,来生成具体的RequestTemplate,当生成代理时,Fegin会为每一个接口方法创建一个RequestTemplate对象,该对象封装了HTTP请求需要的全部信息,如请求参数,请求方法等信息都是在这个过程中确定的.

然后由RequestTemplate生成request,然后把request交给client去处理,这里说的client 可以是jdk中的urlConnection apache 的httpclient 最后client被封装到LoadBalanceClient类,这个类接口ribbon负载均衡发起服务之间的调用

回到顶部入门案例

我们在父工程下创建ch4-fegin 这个父工程在他下面创建 3个模块

1. book-api: 主要作为一个接口给别的服务依赖,包含 实体对象,和api

2. book-service: 主要是作为book-api 的实现类模块

3.book-consumer: 调用book服务的类

下面是代码:

先看book-api的代码

实体类:

/

Created by xiaodao

date: 2019/7/17

*/

@Data

@Builder

@AllArgsConstructor

@NoArgsConstructor

public class Book {

private int id;

private String name;

}

api:

package com.xiaodao.api;

import com.xiaodao.entity.Book;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

/

Created by xiaodao

date: 2019/7/17

/

@RequestMapping("/book")

public interface BookApi {

@GetMapping(value = "list")

List findList();

}

pom:也是空的pom

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

ch4-fegin

com.xiaodao

1.0-SNAPSHOT

4.0.0

ch4-book-api

ch4-book-service的代码:

pom:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

ch4-fegin

com.xiaodao

1.0-SNAPSHOT

4.0.0

ch4-book-service

com.xiaodao

ch4-book-api

${project.version}

org.springframework.cloud

spring-cloud-starter-netflix-eureka-client

bootstrap.yml:

spring:

application:

name: book-service

eureka:

client:

service-url:

defaultZone:

instance:

prefer-ip-address: true

server:

port: 8000

bookserviceImpl:

package com.xiaodao.service;

import com.xiaodao.api.BookApi;

import com.xiaodao.entity.Book;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import org.springframework.web.bind.annotation.ValueConstants;

import java.util.List;

import java.util.concurrent.CopyOnWriteArrayList;

/**

Created by xiaodao

date: 2019/7/17

/

@RestController

@RequestMapping("book")

public class BookServiceImpl implements BookApi {

@GetMapping(value = "list")

@Override

public List findList() {

Book book =Book.builder().id(1).name("第一本书").build();

System.out.println(book);

List list = new CopyOnWriteArrayList();

list.add(book);

return list;

}

}

View Code

bookApplicatiton

package com.xiaodao;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

/

//代码效果参考:http://www.zidongmutanji.com/bxxx/454860.html

Created by xiaodao

date: 2019/7/17

*/

@SpringBootApplication

public class BookApplication {

public static void main(String【】 args) {

SpringApplication.run(BookApplication.class,args);

}

}

View Code

ch4-book-consumer 的代码:

pom:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

ch4-fegin

com.xiaodao

1.0-SNAPSHOT

4.0.0

ch4-book-consumer

org.springframework.cloud

spring-cloud-starter-openfeign

com.xiaodao

ch4-book-api

${project.version}

org.springframework.cloud

spring-cloud-starter-netflix-eureka-client

View Code

bootstrap.yml

spring:

//代码效果参考:http://www.zidongmutanji.com/bxxx/282206.html

application:

name: book-consumer

eureka:

client:

service-url:

defaultZone:

instance:

prefer-ip-address: true

server:

port: 8001

service:就是继承了book-api service的接口

name 是 book-service 的实例名

package com.xiaodao.service;

import com.xiaodao.api.BookApi;

import org.springframework.cloud.openfeign.FeignClient;

/

Created by xiaodao

date: 2019/7/17

/

@FeignClient(name = "book-service")

public interface BookService extends BookApi {

}

controller.调用service.->通过Fegin->book-service

package com.xiaodao.controller;

import com.xiaodao.entity.Book;

import com.xiaodao.service.BookService;

import lombok.AllArgsConstructor;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**

Created by xiaodao

date: 2019/7/17

/

@RestController

@RequestMapping("/book")

@AllArgsConstructor

public class BookController {

private BookService bookService;

@GetMapping("/findList")

public List findList(){

return bookService.findList();

}

}

最后我们启动eurekasever book-service book-consumer 我们可以访问eurekaService

我们去调用book-consumer里的controller方法,看看能不能调用book-service的实现类:

以上就是一个简单的hello word 实现的方法.

传参数

1.单个参数时候没有问题的

2.多个参数用post方法 (@requestBody Book book) feign是不支持 get方法传递实体对象的

3.如果想用get方式传实体对象需要将feign默认的URLConnection连接换成httpClient

回到顶部fegin 性能优化

gzip压缩

gzip介绍:gzip是一种数据格式,采用defalte算法压缩data gzip是一种流行的文件压缩算法,应用十分广泛,尤其是在liunx平台

gzip能力: 当gzip压缩一个纯文本文件时,效果是非常明显,大约可以减少70%以上的文件大小

gzip作用: 网络数据通过压缩之后实际上降低了网络传输的字节数,最明显的好处时候加快网页的加载速度,网页加载速度加快的好处不言而喻,除了节省流量以外,改善用户体验外,另一个潜在的好处是Gzip与搜索引擎的抓取工具有着更好的关系,例如:Google 就可以通过读取Gzip文件来比普通手工抓取 更快的检索网页

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

1. 客户端向服务器请求中带有:Accept-Encoding:Gzip,deflate字段,向服务器表示,客户端支持的压缩格式(gzip或者 deflate),如果不发送消息头,服务器是不会压缩的

2. 服务端收到请求之后,如果发现请求中含有Accept-Encoding字段,并且支持该类型的压缩,就对响应报文压缩之后在返回客户端,并且携带Content-Encoding:gzip消息头,表示报文是经过压缩的

3. 客户端接到服务器的响应之后,先判断是否有Content-Encoding消息头,如果有,按格式解压报文,否者按正常处理

我们在baidu搜索下发送一个消息

看到是百度服务器是经过压缩的

然后我们在看下我们刚才的代码.

可以看出是没有经过压缩的.

那我们使用fegin怎么做压缩呢?

spring:

application:

name: book-consumer

eureka:

client:

service-url:

defaultZone:

instance:

prefer-ip-address: true

server:

port: 8001

### Feign 配置

feign:

compression:

request:

# 开启请求压缩

enabled: true

# 配置压缩的 MIME TYPE

mime-types: text/xml,application/xml,application/json

# 配置压缩数据大小的下限

min-request-size: 2048

response:

# 开启响应压缩

enabled: true

这里有坑,当我在book-consumer 配置了压缩的时候,我发现我们请求是配置了gzip压缩了但是服务器并没有压缩.为什么呢?是当我们使用浏览器访问的时候没有压缩.

当我们在配置spring boot压缩之后:在看控制台就显示服务器也压缩过了

spring:

application:

name: book-consumer

eureka:

client:

service-url:

defaultZone:

instance:

prefer-ip-address: true

server:

port: 8001

#配置spring boot 压缩

compression:

enabled: true

# mime-types:

### Feign 配置

feign:

compression:

request:

# 开启请求压缩

enabled: true

# 配置压缩的 MIME TYPE

mime-types: text/xml,application/xml,application/json

# 配置压缩数据大小的下限

min-request-size: 2048

response:

# 开启响应压缩

enabled: true

View Code

也可以不写fegin的压缩,直接 就用springboot的压缩就好了.

HTTP连接池优化

为什么http连接池能提升性能?

http的背景原理

1.俩台服务器建立http的过程是很富在的工程,涉及到了多个数据包的交换,并且也耗费时间

2. http连接需要3次握手4次分手开销很大,这一开销对于大量比较小的http消息来说更大

优化解决方案

1.如果我们采用http连接池,节约了大量的3次握手4次分手,这样能大大的提高性能

2.fegin的http客户端支持3种框架 : HttpURLConnection httpclient okhttp 默认是HTTPURLConnection.

3.传统的HTTPURLConnection是JDK自带的,并不支持线程池,如果要实现连接池的机制,还需要自己管理连接对象,对于网络请求这种底层相对复杂的操作,如果有可用的方案,也没有必要自己去实现

4.HttpClient相比于JDK自带的URLConnection,它封装了访问http的请求头,参数,内容体响应等等,它不仅是客户端发送http请求变的容易,而且方便开发人员测试接口(基于http协议), 也提高的效率,也方便提高代码的健壮性,另外高并发大量请求网络的时候,还是使用"连接池"提升吞吐量的.

使用httpClient连接池

1.在book-consumer 的pom中:加入

org.apache.httpcomponents

httpclient

4.5.5

io.github.openfeign

feign-httpclient

9.5.1

2.在bootstrap.yml中加入

spring:

application:

name: book-consumer

eureka:

client:

service-url:

defaultZone:

instance:

prefer-ip-address: true

server:

port: 8001

#配置sprin

相关文章
|
2月前
|
JSON Java 数据格式
【微服务】SpringCloud之Feign远程调用
本文介绍了使用Feign作为HTTP客户端替代RestTemplate进行远程调用的优势及具体使用方法。Feign通过声明式接口简化了HTTP请求的发送,提高了代码的可读性和维护性。文章详细描述了Feign的搭建步骤,包括引入依赖、添加注解、编写FeignClient接口和调用代码,并提供了自定义配置的示例,如修改日志级别等。
110 1
|
7月前
|
应用服务中间件 nginx 微服务
SpringCloud解决feign调用token丢失问题
【5月更文挑战第2天】在feign调用中可能会遇到如下问题: * 同步调用中,token丢失,这种可以通过创建一个拦截器,将token做透传来解决 * 异步调用中,token丢失,这种就无法直接透传了,因为子线程并没有**token**,这种需要先将token从父线程传递到子线程,再进行透传
460 3
|
3月前
|
负载均衡 Java Nacos
SpringCloud基础2——Nacos配置、Feign、Gateway
nacos配置管理、Feign远程调用、Gateway服务网关
SpringCloud基础2——Nacos配置、Feign、Gateway
|
3月前
|
前端开发 API 微服务
SpringCloud微服务之间使用Feign调用不通情况举例
SpringCloud微服务之间使用Feign调用不通情况举例
628 2
|
3月前
|
Java API 开发者
【已解决】Spring Cloud Feign 上传文件,提示:the request was rejected because no multipart boundary was found的问题
【已解决】Spring Cloud Feign 上传文件,提示:the request was rejected because no multipart boundary was found的问题
608 0
|
负载均衡 Java Maven
微服务技术系列教程(23) - SpringCloud- 声明式服务调用Feign
微服务技术系列教程(23) - SpringCloud- 声明式服务调用Feign
116 0
SpringCloud Feign报错Method has too many Body parameters
SpringCloud Feign报错Method has too many Body parameters
|
7月前
|
Nacos
SpringCloud Feign使用
SpringCloud Feign使用
50 1
|
7月前
|
JSON Java Apache
Spring Cloud Feign 使用Apache的HTTP Client替换Feign原生httpclient
Spring Cloud Feign 使用Apache的HTTP Client替换Feign原生httpclient
412 0
|
7月前
|
Java Spring
spring cloud 通过feign请求动弹设置请求头heades
spring cloud 通过feign请求动弹设置请求头heades
376 0