Feign

声明式服务调用Feign

使用RestTemplate进行调用其他服务的API的时候,请求的参数需要在URL中进行拼接,当有多参数的时候,拼接字符串的方式效率就会显得比较低下,而Feign能够解决这样的问题

什么是Feign

Feign是SpringCloud提供的声明式模板化的Http客户端,只需要创建一个接口并且添加一个注解即可,SpringCloud集成了Feign并且对其进行了增强,Feign支持SpringMvc的注解,Feign默认集成Ribbon,也实现了负载均衡的效果
在这里插入图片描述

案例展示

1.首先创建服务提供者
在这里插入图片描述
application.yml

server:
  port: 9092
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.112.130:8848  
  application:
    name: feign-provider #服务名称

controller

@RestController
@RequestMapping("/provider")
public class ProviderController {
    @Autowired
    private UserService userService;

    @RequestMapping("/getUserById/{id}")
    public User getUserById(@PathVariable Integer id){
        return userService.getUserById(id);
    }
    @RequestMapping("/deleteUserById")
    public User deleteUserById(@RequestParam("id")Integer id){
       return userService.deleteUserById(id);
    }

    @RequestMapping("addUser")
    public User addUser(@RequestBody User user){
     return   userService.addUser(user);
    }
}

Service

public interface UserService {
    User getUserById(Integer id);

    User deleteUserById(Integer id);

    User addUser(User user);
}

2.创建Feign接口
导入Feign依赖

  <!--Spring Cloud OpenFeign Starter -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
@FeignClient("feign-provider")
@RequestMapping("/provider")
public interface UserFeign {
    @RequestMapping("/getUserById/{id}")
    User getUserById(@PathVariable("id") Integer id); //restful拼接传参

    @RequestMapping("/deleteUserById")
    User deleteUserById(@RequestParam("id")Integer id);//?拼接URL

    @RequestMapping("addUser")
    User addUser(@RequestBody User user);//将User对象转成json串
}

Feign接口中接受的参数大致分三大类:restful路径传参,?拼接传参,java对象为参数(其中将对象转换成了json串)
注意:此时Feign接口中的SpirngMvc注解不再是它原本的意思,而是在Feign中的独有的意思,通过这些注解将他们拼接成URL
3.创建消费者
导入依赖

<!--nacos客户端-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--feign接口-->
        <dependency>
            <groupId>com.li</groupId>
            <artifactId>feign_interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

application.yml

server:
  port: 8080
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.112.130 #nacos服务的地址
  application:
    name: feign-consumer

Controller

@RestController
@RequestMapping("/consumer")
public class ConsumerController {
   @Autowired
   private UserFeign userFeign;

    @RequestMapping("/getUserById/{id}")
    public User getUserById(@PathVariable("id")Integer id){
  return userFeign.getUserById(id);
    }


    @RequestMapping("/deleteUserById")
   public User deleteUserById(@RequestParam("id")Integer id){
       return userFeign.deleteUserById(id);
    }

    @RequestMapping("addUser")
   public User addUser(@RequestBody User user){
      return   userFeign.addUser(user);
    }
}
启动类

```java
@SpringBootApplication
@EnableFeignClients//开启feign接口扫描
@EnableDiscoveryClient//向注册中心注册该服务,并可以获取其他服务的调用地址
public class FeignConsumerApp {
    public static void main(String[] args) {
        SpringApplication.run(FeignConsumerApp.class);
    }
}

测试
在这里插入图片描述在这里插入图片描述

Feign原理

在这里插入图片描述 在这里插入图片描述
1.用过@EnableFeignClients注解扫描Feign的注解,扫描遍历feign接口的包,生成feign接口的代理对象放入spring容器中
2.为feign接口的方法创建RequestTemplate:当consumer调用feign代理类时,代理类会调用SynchronousMethodHandler.invoke()创建RequestTemplate
3.代理类会通过RequestTemplate创建Request,然后client(URLConnetct、HttpClient、OkHttp)使用Request发送请求

 Object executeAndDecode(RequestTemplate template) throws Throwable {
        //生成请求对象
        Request request = this.targetRequest(template);
        if (this.logLevel != Level.NONE) {
            this.logger.logRequest(this.metadata.configKey(), this.logLevel, request);
        }

        long start = System.nanoTime();

        Response response;
        try {
            //发起请求
            response = this.client.execute(request, this.options);
        } catch (IOException var15) {
            ... ... ...

            throw FeignException.errorExecuting(request, var15);
        }
 } 

也就是说feign的注解是用来拼接URL参数的
断点验证
在这里插入图片描述在这里插入图片描述

Feign优化

Feign的优化分为三种:1.开启feign日志 2.feign超时 3.http连接池 4.gzip压缩
1.开启feign日志

feign:
  client:
    config:
      default:
  loggerLevel: full
  logging:
    level:
      com.li.feign: debug

2.feign超时
模拟超时
修改provider生产者

public class UserServiceImpl implements UserService {
    @Override
    public User getUserById(Integer id) {
        try {
            Thread.sleep(2000);//休眠2s
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new User(id,"lz1",18);
    }

在这里插入图片描述结果超时
进行feign时间配置

feign:
			  client:
			    config:
			      feign-provider:
				ConnectTimeout: 5000 #请求连接的超时时间
				ReadTimeout: 5000 #请求处理的超时时间

或者

ribbon:
			   ConnectTimeout: 5000 #请求连接的超时时间
			   ReadTimeout: 5000 #请求处理的超时时间

日志的配置会影响feign的超时时间

3.http连接池
http 的背景原理
a. 两台服务器建立 http 连接的过程是很复杂的一个过程,涉及到多个数据包的交换,并
且也很耗时间。
b. Http 连接需要的 3 次握手 4 次分手开销很大,这一开销对于大量的比较小的 http 消
息来说更大。
2优化解决方案
a. 如果我们直接采用 http 连接池,节约了大量的 3 次握手 4 次分手;这样能大大提升吞
吐率。
b. feign 的 http 客户端支持 3 种框架;HttpURLConnection、httpclient、okhttp;默认是
HttpURLConnection。
c. 传统的 HttpURLConnection 是 JDK 自带的,并不支持连接池,如果要实现连接池的
机制,还需要自己来管理连接对象。对于网络请求这种底层相对复杂的操作,如果有可用的
其他方案,也没有必要自己去管理连接对象。
d. HttpClient 相比传统 JDK 自带的 HttpURLConnection,它封装了访问 http 的请求头,
参数,内容体,响应等等;它不仅使客户端发送 HTTP 请求变得容易,而且也方便了开发人
员测试接口(基于 Http 协议的),即提高了开发的效率,也方便提高代码的健壮性;另外
高并发大量的请求网络的时候,还是用“连接池”提升吞吐量。

在消费者端导入依赖

<dependency>
		    <groupId>io.github.openfeign</groupId>
		    <artifactId>feign-httpclient</artifactId>
</dependency>

在这里插入图片描述此时client由最初的ClientDefault变成了ApacheHttpClient

4.Feign的gzip压缩
Feign 是通过 http 调用的,那么就牵扯到一个数据大小的问题。如果不经过压缩就发送请求、获取响应,那么会因为流量过大导致浪费流量,这时就需要使用数据压缩,将大流量压缩成小流量。
修改application.yml配置文件

server:
  port: 8080
  compression:
    enabled: true #开启gzip压缩
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.112.130 #nacos服务的地址
  application:
    name: feign-consumer
ribbon:
  ConnectTimeout: 5000 #请求连接的超时时间
  ReadTimeout: 5000 #请求处理的超时时间

在这里插入图片描述当改为gzip压缩后,响应头的Content-Encoding变成了gzip的方式

在这里插入图片描述

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值