Feign 的基础认识

本文介绍了Feign的基础知识,包括Feign的工作原理、接口定义、超时时间配置以及优化方法。Feign是Spring Cloud的一个组件,提供声明式的服务调用,通过动态代理实现接口调用。Feign接口传参有三种方式:?传参、restful传参和pojo传参。默认超时时间为Ribbon的1秒,可通过配置文件设置超时时间。Feign的优化包括使用http连接池、支持gzip压缩、调整超时时间和开启日志记录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Feign概述

Feign是Spring Cloud提供的声明式、模板化的HTTP客户端,运行在consumerdua端, 它使得调用远程服务就像调用本地服务一样简单,只需要创建一个接口并添加一个注解即可。

Spring Cloud集成Feign并对其进行了增强,使Feign支持了Spring MVC注解;Feign默认集成了Ribbon,所以Fegin默认就实现了负载均衡的效果。(ribbon+restTemplate)+优化=feign

二、启动类

  • 在ConsumerApplication启动类上,添加@EnableFeignClients注解,开启Feign接口扫描功能
@SpringBootApplication
@EnableDiscoveryClient
//@EnableFeignClients(basePackages = "com.bjpowernode.feign")
@EnableFeignClients//开启feign接口扫描
public class ConsumerApp {

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

 三、feign的接口类

  • 编写Feign客户端接口类UserFeign
  • 注解@FeignClient声明Feign的客户端,指明服务名称
  • 接口定义的方法,采用SpringMVC的注解。Feign会根据注解帮我们生成URL地址
  • Feign会通过动态代理,帮我们生成实现类。
  • fallbackFactory是工厂类,用于生成 fallback 类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码。
  • fallback:定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback 指定的类必须实现 @FeignClient 标记的接口。
@FeignClient(value = "feign-provider", fallbackFactory = UserFeignFallback.class)
@RequestMapping(value = "/provider")
public interface UserFeign {
    @RequestMapping(value = "/getUserById/{id}")
    public User getUserById(@PathVariable(value = "id") Integer id);
  •  fallback就是调用失败或者请求超时时,调用的数据。实现类必须用@Component注解,以保证注入到spring容器
  • 在使用FeignClient时,Spring会按name创建不同的ApplicationContext,通过不同的Context来隔离FeignClient的配置信息,在使用配置类时,不能把配置类放到Spring App Component scan的路径下,否则,配置类会对所有FeignClient生效

四、feign接口传参的三种方式

  1.    ?传参          @RequestParam("id")   和controller中的RequestParam注解有所不同,必须指明参数名,不管相同否 【拼接?形式的url】
  2.    restful传参    @PathVariable("id")   和controller中的PathVariable注解有所不同,必须指明参数名,不管相同否 【拼接restful形式的url】
  3.    pojo               @RequestBody controller中是注解放在形参前,可以json转对象,这里是对象转json 【获取请求体中的json串】

五、超时时间

  • 通过启动类发现 OpenFeign 的默认的 connectTimeout 是 10 秒,readTimeout 是 60 秒。模拟请求超时,睡一会
@Service
public class UserServiceImpl implements UserService {

	@Override
	public User getUser() {
        //模拟网络延迟
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return new User(1,"王粪堆",18);
	}
}

会报错

其实因为 OpenFeign 集成了 Ribbon,Ribbon 的默认超时连接时间、读超时时间都是 1 秒

如果 OpenFeign 没有设置对应得超时时间,那么将会采用 Ribbon 的默认超时时间

可以在yml文件设置OpenFeign的请求超时时间,和Ribbon的请求超时时间

 openfeign可单独配置某个服务的超时时间

 

 但是Ribbon和feign的设置,只有一个会生效,同时设置优先生效OpenFeign,注掉 OpenFeign 超时时间配置之后,就变成了使用设置的 Ribbon 的超时时间

超时总结:

不设置超时时间默认是Ribbon 的默认超时连接时间、读超时时间都是 1 秒。同时设置,生效Feign。

六、Feign 工作原理

 

  • 在开发微服务应用时,我们会在主程序入口添加 @EnableFeignClients 注解开启对 Feign Client 扫描加载处理。根据 Feign Client 的开发规范,定义接口并加 @FeignClients 注解。
  • 当程序启动时,会进行包扫描,扫描所有 @FeignClients 的注解的类,并将这些信息注入 Spring IOC 容器中。当定义的 Feign 接口中的方法被调用时,通过JDK的代理的方式,来生成具体的 RequestTemplate。当生成代理时,Feign 会为每个接口方法创建一个 RequetTemplate 对象,该对象封装了 HTTP 请求需要的全部信息,如请求参数名、请求方法等信息都是在这个过程中确定的。

public void registerFeignClients(AnnotationMetadata metadata,
			BeanDefinitionRegistry registry) {

		………………
if (clients == null || clients.length == 0) {
			ClassPathScanningCandidateComponentProvider scanner = getScanner();
			scanner.setResourceLoader(this.resourceLoader);
			scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));
			Set<String> basePackages = getBasePackages(metadata);
			for (String basePackage : basePackages) {
				candidateComponents.addAll(scanner.findCandidateComponents(basePackage));
			}
		}
		………………
		for (BeanDefinition candidateComponent : candidateComponents) {
			if (candidateComponent instanceof AnnotatedBeanDefinition) {
				// verify annotated class is an interface
				AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
				AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
				Assert.isTrue(annotationMetadata.isInterface(),
						"@FeignClient can only be specified on an interface");

				Map<String, Object> attributes = annotationMetadata
						.getAnnotationAttributes(FeignClient.class.getCanonicalName());

				String name = getClientName(attributes);
				registerClientConfiguration(registry, name,
						attributes.get("configuration"));

				registerFeignClient(registry, annotationMetadata, attributes);
			}
		}
	}

  • 然后由 RequestTemplate 生成 Request,然后把 Request 交给 Client 去处理,这里指的 Client 可以是 JDK 原生的 URLConnection、Apache 的 Http Client 也可以是 Okhttp。最后 Client 被封装到 LoadBalanceclient 类,这个类结合 Ribbon 负载均衡发起服务之间的调用。

 

七、@FeignClient 注解:

  •     name:指定 Feign Client 的名称,如果项目使用了 Ribbon,name 属性会作为微服务的名称,用于服务发现。
  •     url:url 一般用于调试,可以手动指定 @FeignClient 调用的地址。
  •     decode404:当发生404错误时,如果该字段为 true,会调用 decoder 进行解码,否则抛出 FeignException。
  •     configuration:Feign 配置类,可以自定义 Feign 的 Encoder、Decoder、LogLevel、Contract。
  •     fallback:定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback 指定的类必须实现 @FeignClient 标记的接口。
  •     fallbackFactory:工厂类,用于生成 fallback 类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码。
  •     path:定义当前 FeignClient 的统一前缀。

八、Feign的优化

1、http连接池

Feign底层发起http请求

其底层客户端实现包括三个:

  1. • URLConnection:默认实现,不支持连接池,默认使用这个
  2. Apache HttpClient :支持连接池
  3. OKHttp:支持连接池

因此提高Feign的性能主要手段就是使用连接池代替默认的URLConnection。

  • 消费者中加依赖(如果有公共的接口工程,可以直接加在接口的pom.xml中)
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>
  • 开启连接池(因为默认为true开启,添加依赖后就行,可不写连接池配置,还可以配其他配置,入最大连接数等)

 开启后便切换为HttpClient

2、支持gzip压缩

现在打大多数主流浏览器都支持多种压缩格式,gzip广为好评。在application.yml中修改开启就可优化传输速度。

 

 3、feign超时

上面第五节已说明,可以全局设置ribbon的超时时间(不设置默认为1s,),也可设置feign的全局超时时间和指定服务超时时间,可防止异常出现。

4、开启feign日志

 两个需要同时配置。

超时时间和日志配置都没有智能提醒,这里提供一份供大家CV大法,防止手残

server:
  port: 80
  compression:
    enabled: true #开启gzip压缩
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.163.131:8848 #nacos的服务地址
        #namespace: dev #可自定义,读取开发环境的配置文件 namespace隔离 服务隔离
        #group: NACOS_GROUP #读取NACOS_GROUP这个分组下的配置文件,分组隔离 服务隔离
  application:
    name: feign-consumer #向注册中心注册的名字
#ribbon:
#  ConnectTimeout: 5000 #请求连接的超时时间
#  ReadTimeout: 5000 #请求处理的超时时间
feign:
  client:
    config:
      default: # 全局配置,也可以换成指定的服务feign-provider
        connectTimeout: 5000 #请求连接的超时时间
        readTimeout: 5000 #请求处理的超时时间
        loggerLevel: full #内容全部输出
logging:
  level:
    com.shenjian.feign: debug # 开启debug级别的日志

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值