Feign

Feign

1 Feign概述

只需要接口加注解即可实现调用远程服务像调用本地服务一样

通过创建与provide服务端controller相对应的接口,来简洁的实现 “调用接口方法即向服务端发送请求并利用返回值接收响应” 的操作,消费端只需要通过@EnableFeignClients开启feign接口扫描,为其创建代理对象注入ioc,使用时获取对象并调用其方法即可直接访问服务端

2 Feign使用

  1. 新建服务:feign-provide

    • pom.xml

      • <dependency>
        			<groupId>org.springframework.boot</groupId>
        			<artifactId>spring-boot-starter-web</artifactId>
        		</dependency>
        		<dependency>
        			<groupId>com.alibaba.cloud</groupId>
        			<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        		</dependency>
        		<dependency>
        			<groupId>com.moyu</groupId>
        			<artifactId>common</artifactId>
        			<version>1.0-SNAPSHOT</version>
        		</dependency>
        
    • UserController

      • @RestController
        @RequestMapping("/provide")
        public class UserController {
        
            @Autowired
            private UserService userService;
        
            @GetMapping("/getUserById/{id}")
            public User getUserById(@PathVariable("id") Integer id) {
                return userService.getUserById(id);
            }
        }
        
    • application.yml

      • server:
              port: 8085
        spring:
              application:
                    name: feign-provide
              cloud:
                    nacos:
                          discovery:
                                server-addr: 192.168.40.132:8848
        
  2. 创建接口:feign-interface

    • pom.xml 导入 openfeign依赖

      • 	<dependencies>
        		<dependency>
        			<groupId>org.springframework.cloud</groupId>
        			<artifactId>spring-cloud-starter-openfeign</artifactId>
        			<version>2.2.1.RELEASE</version>
        		</dependency>
                <!--自定义common包存储pojo实体类-->
        		<dependency>
        			<groupId>com.moyu</groupId>
        			<artifactId>common</artifactId>
        			<version>1.0-SNAPSHOT</version>
        		</dependency>
        	</dependencies>
        
    • 定义接口 UserFeign,接口内容与provide的UserController一一对应,包括类注解请求路径和方法请求路径

      • @RequestMapping("/provide")
        @FeignClient("feign-provide")
        public interface UserFeign {
        
            //@PathVariable("id"),注解必须传参
            @GetMapping("/getUserById/{id}")
            public User getUserById(@PathVariable("id") Integer id);
        }
        
  3. 创建消费端:feign-customer

    • pom.xml导入自定义的interface包和nacos-discovery依赖

      • <dependencies>
        		<dependency>
        			<groupId>org.springframework.boot</groupId>
        			<artifactId>spring-boot-starter-web</artifactId>
        		</dependency>
        		<dependency>
        			<groupId>com.alibaba.cloud</groupId>
        			<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        		</dependency>
        		<dependency>
        			<groupId>com.moyu</groupId>
        			<artifactId>feign-interface</artifactId>
        			<version>1.0-SNAPSHOT</version>
        		</dependency>
        	</dependencies>
        
    • UserController

      • @RestController
        @RequestMapping("/user")
        public class UserController {
        
            @Autowired
            private UserFeign userFeign;
        
            @GetMapping("/getUserById/{id}")
            public User getUserById(@PathVariable("id") Integer id) {
                return userFeign.getUserById(id);
            }
        
        }
        
    • app,开启Feign接口扫描,注入ioc容器

      • @SpringBootApplication
        @EnableDiscoveryClient
        @EnableFeignClients
        public class FeignConsumerApp {
            public static void main(String[] args) {
                SpringApplication.run(FeignConsumerApp.class, args);
            }
        }
        
  4. 测试

    • 测试结果

3. Feign原理

  1. 扫描 feign 接口,创建代理对象并交给 ioc 容器管理
    • 使用@EnableFeignClients注解开启feign接口扫描,FeignClientsRegistrar.registerFeignClients() 扫描所有被 @FeignClient 标记的接口,创建代理类并注入 ioc 容器管理
  2. 根据 feign 接口上的注解创建 RequestTemplate 类
    • 当在controller类中调用 feign 接口对象的方法时,代理对象会调用 invoke() 方法根据接口上面的注解生成 RequestTemplate(url, requestMethod, body)
  3. 发送请求
    • 通过 RequestTemplate 来创建 Request 请求,然后 client() 方法使用Request发送请求

4. Feign的三种传参方式

请求处理流程:前端发送请求 -> 消费端controller层接收请求和参数 -> 调用feign接口方法并传递参数 -> feign接口根据方法上的注解转换为请求,根据方法参数转换为请求参数,向provide服务端发送转换后的请求和参数 -> 服务端controller接收请求及参数,调用service处理并得到返回值,将返回值封装到响应中并返回 -> feign 接口接收响应并进行解析,得到返回值并将其返回给消费端的controller -> 消费端得到返回值,并对其封装返回给前端

4.1 问号“?”传参

  • @RequestMapping("/user/getUserById")
    public User getUserById(@RequestParam("id") Integer id);
    
  • 消费端 controller 调用:userFeign.getUserById(1)

  • feign发送请求:http://ip:port/user/getUserById?id=1 到provide服务端

  • @RequestMapping("/deleteBatch")
    String deleteBatch(@RequestParam("ids") Integer[] ids);
    
  • 消费端 controller 调用:userFeign.deleteBatch(new int[]{1, 2, 4});

  • feign发送请求:ip:port/user/deleteBatch?ids=1,2,4 到provide服务端

4.2 restful 传参

  • @RequestMapping("/user/getUserById/{id}")
    public User getUserById(@PathVariable("id") Integer id);
    
  • 消费端 controller 调用:userFeign.getUserById(1)

  • feign发送请求:ip:port/user/getUserById/1 到provide服务端

4.3 pojo对象传参

  • @RequestMapping("/user/add")
    public Result add(@RequestBody User user);
    
  • 消费端controller调用:userFeign.add(new User(3, “王二狗”, 16))

  • feign发送请求:http://ip:port/user/add 并将参数user封装到请求体中发送请求到provide服务端

5. Feign的优化

5.1 开启日志

Feign中的四种日志级别

  • NONE【性能最佳,适用于生产】:不记录任何日志(默认值)
  • BASIC【适用于生产环境追踪问题】:仅记录请求方法,URL,响应状态码及执行时间
  • HEADERS:在BASIC的基础上,记录请求和响应的 header
  • FULL【适用于开发及测试环境定位问题:记录请求和响应的 header,body 和元数据

5.1.1 配置文件方式(常用)

# 显示feign日志
feign:
	client:
    	config:
        	default:
            	logger-Level: BASIC
#  开启log4j的日志
logging:
	level:
    	com.moyu.feign: debug	# 日志只在此包中生效,并且级别是 debug

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ScdadQr0-1665651815317)(C:\Users\wangp\AppData\Roaming\Typora\typora-user-images\image-20221013163140719.png)]

5.1.2 配置类形式

  1. 配置文件中开启日志

    • #  开启log4j的日志
      logging:
      	level:
          	com.moyu.feign: debug	# 日志只在此包中生效,并且级别是 debug
      
  2. 配置类中开启feign日志

    • 全局配置

      • @Configuration
        public class FeignLog {
            @Bean
            public Logger.Level feignLogLevel(){
                return Logger.Level.FULL;
            }
        }
        
    • 局部配置

      • // @Configuration,去掉注解
        public class FeignLog {
            @Bean
            public Logger.Level feignLogLevel(){
                return Logger.Level.FULL;
            }
        }
        
      • @FeignClient(name="feign-provide", path = "/user", configuration = FeignLog.class)
        public interface UserService {
            @GetMapping("/get/{id}")
            public String get(@PathVariable("id") Integer id);
        }
        

5.2 GZIP压缩

GZIP是一种数据格式,采用deflate 压缩算法,纯文本文件压缩后可减少 70% 以上的大小

使用此方式压缩文件减少了网络请求中传输文件的字节数,提升了传输效率,加快了网页加载速度

Feign开启GZIP

项目中启用GZIP(consumer)

server:
  port: 82
  # 开启浏览器->consumer的gzip压缩
  compression:
    enabled: true

feign:
  compression:
    request:
      # 开启feign<->provide服务端的gzip压缩
      enabled: true
    response:
      # 开启响应压缩
      enabled: true

将feign日志等级调为FULL,即可看到

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XjQnpDcR-1665651815318)(C:\Users\wangp\AppData\Roaming\Typora\typora-user-images\image-20221013163946659.png)]

5.3 Http连接池

每次http请求的建立过程都要经历三次握手和断开连接的四次挥手,效率太低,可创建http连接池,提前创建http请求连接,访问请求时直接从连接池取出请求连接即可进行数据传输,传输完成请求再返回连接池,实现了重复利用,并且提升了效率

引入依赖即可自动创建连接池

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

5.4 Feign的超时时间设置

feign请求超时时间默认为 1s,当加入日志处理时请求超时时间会延长,有些请求可能需要很长时间处理,则需要自定义配置超时时间

去掉feign的日志记录之后,在服务端接收请求后先sleep(1000)再处理,则会抛出超时异常

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MzgjAALs-1665651815319)(C:\Users\wangp\AppData\Roaming\Typora\typora-user-images\image-20221013165826557.png)]

配置文件配置

  1. 通过 feign 配置(常用)

    • feign:
       	client:
       		config:
               feign-provide: # 对应服务提供者
                   ConnectionTimeout: 5000 #请求连接的超时时间
                   ReadTimeout: 5000 #请求处理的超时时间
      
  2. 通过ribbon 配置:

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

配置类配置

//全局配置
@Configuration
public class FeignConfig{
    @Bean
    public Request.Options options(){
        return  new Request.Options(5000, 10000);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值