概述
Spring Cloud Feign是一个声明式的HTTP客户端,你可以通过编写接口的方式来定义服务之间的通信接口。Feign会根据接口定义自动生成实现类,无需手动编写HTTP请求的代码。
可以以Java接口注解的方式调用Http请求,而不用像Java中通过封装HTTP请求报文的方式直接调用。
声明式:指的是通过使用注解和编写接口的方式来定义服务之间的通信接口,Feign能够自动生成实现类,将接口方法映射为HTTP请求,并处理请求的发送和响应的处理。而无需手动编写HTTP请求的代码。
功能
声明式的http客户端:以Java接口注解的方式调用Http请求
负载均衡:与Ribbon(或其他负载均衡框架)集成,使用负载均衡的前提是先与服务发现的框架集成,在服务发现的基础上才能根据负载均衡框架做负载均衡
服务发现:与Eureka(或其他服务发现框架如nacos)集成, Feign会自动从服务注册中心获取可用的服务实例(根据@FeignClient的name属性)。
错误处理:Feign提供了默认的错误处理机制,可以处理常见的HTTP错误状态码。你可以通过自定义的错误解码器(ErrorDecoder)来处理特定的错误响应。
日志记录:Feign提供了日志记录的功能,可以记录请求和响应的详细信息,方便调试和排查问题。
错误处理功能说明
以下是一些常见的错误处理功能:
1. 异常转换:当服务调用失败或返回错误状态码时,Feign可以将底层的HTTP异常转换为更具体的异常类型。这样,你可以根据不同的异常类型来处理不同的错误情况。例如,Feign可以将HTTP 404错误转换为FeignException.NotFound异常,HTTP 500错误转换为FeignException.InternalServerError异常等。
2. 自定义错误处理器:你可以通过实现ErrorDecoder接口来自定义错误处理器。该接口允许你根据不同的错误响应来自定义异常的生成方式。你可以在自定义错误处理器中处理特定的错误响应,并将其转换为适合你的应用程序的异常类型。
3. Fallback机制:Feign还提供了一种回退机制,即当服务调用失败时,可以执行备用逻辑。你可以为Feign客户端接口定义一个回退实现类,该类实现了与原始接口相同的方法,并提供备用的逻辑。当服务调用失败时,Feign将调用回退实现类中的对应方法,以执行备用逻辑。
4. 全局错误处理器:你可以通过实现ErrorDecoder接口的decode方法来定义全局的错误处理器。该方法将在所有Feign客户端接口的错误处理中被调用,以处理通用的错误情况。你可以在全局错误处理器中定义如何处理特定的错误响应,并将其转换为适合你的应用程序的异常类型。
通过这些错误处理功能,你可以更好地处理与服务通信时可能出现的异常情况,提高应用程序的可靠性和容错性。
优先级说明:fallback机制>异常转换>自定义错误处理器>全局错误处理器
异常转换功能说明:默认是开启的,Feign使用了feign.codec.ErrorDecoder接口来处理异常转换。默认情况下,Feign使用feign.codec.ErrorDecoder.Default作为默认的错误处理器。该默认处理器会根据不同的HTTP状态码来生成相应的Feign异常类型。
Fallback机制说明:
1. 定义回退实现类:首先,你需要在调用端为Feign客户端接口定义一个回退实现类。回退实现类实现了与原始接口相同的方法,并提供备用的逻辑。回退实现类可以在服务调用失败时被调用,以执行备用逻辑。
@Component
public class YourFeignClientFallback implements YourFeignClient {
@Override
public String yourMethod() {
// 执行备用逻辑
return "Fallback response";
}
}
2. 启用回退机制:为了启用fallback机制,你需要在Feign客户端接口上使用@FeignClient注解的fallback属性,将回退实现类指定为回退逻辑的实现。
@FeignClient(name = "your-service", fallback = YourFeignClientFallback.class)
public interface YourFeignClient {
@GetMapping("/your-endpoint")
String yourMethod();
}
3.使用Feign客户端:跟正常调用feign客户端一样
@RestController
public class YourController {
@Autowired
private YourFeignClient yourFeignClient;
@GetMapping("/your-api")
public String yourApi() {
return yourFeignClient.yourMethod();
}
}
全局错误处理器说明:
Feign提供了一种全局错误处理器的机制,允许你在所有Feign客户端接口的错误处理中定义通用的错误处理逻辑。通过实现ErrorDecoder接口的decode方法,你可以自定义全局错误处理器。
public class GlobalErrorDecoder implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {
// 处理错误响应并返回适当的异常类型
// ...
return new CustomException("Custom error message");
}
}
册全局错误处理器:为了将全局错误处理器应用于所有的Feign客户端接口,你需要在Feign客户端配置类中注册全局错误处理器。
@Configuration
public class FeignClientConfiguration {
@Bean
public ErrorDecoder errorDecoder() {
return new GlobalErrorDecoder();
}
}
日志记录功能说明
日志记录功能,可以帮助你在调试和排查问题时更好地了解Feign的请求和响应信息
启用日志记录:要启用Feign的日志记录功能,你需要在应用程序的配置文件中添加以下配置:
logging.level.<feign-client-name>=<log-level>
日志级别,例如INFO、DEBUG、ERROR等
这种方式适用于希望为特定的Feign客户端设置不同的日志级别的情况。
Feign日志类型配置:
logging.level.feign.<logger-name>=<log-level>
其中<logger-name>是Feign内部日志记录器的名称。
以下是一些常见的Feign内部日志记录器名称:
- feign.Logger:Feign的请求和响应日志记录器。
- feign.Retryer:Feign的重试日志记录器。
- feign.Contract:Feign的契约日志记录器。
- feign.Client:Feign的客户端日志记录器。
日志级别,例如INFO、DEBUG、ERROR等
全局feign日志配置:
feign.client.config.default.loggerLevel=<log-level>
日志级别:你可以根据需要设置不同的日志级别,以控制日志记录的详细程度。常见的日志级别包括:
- NONE:不记录任何日志。
- BASIC:仅记录请求方法、URL和响应状态码。
- HEADERS:记录请求和响应的基本信息,包括头部信息。
- FULL:记录请求和响应的详细信息,包括头部、正文和元数据。
该级别将应用于所有的Feign客户端。这种方式适用于希望统一设置所有Feign客户端的日志级别的情况。
使用
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
被调用方服务B编写接口
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ServiceBController {
@GetMapping("/api/data")
public String data() {
return "data";
}
}
调用发起方服务A, 在Spring Boot的配置类上添加@EnableFeignClients注解来启用Feign客户端。这个注解告诉Spring Boot应用程序扫描并创建Feign客户端接口的代理实现类,以便进行服务调用。
被调用方服务B的启动类上不需要使用@EnableFeignClients注解
@SpringBootApplication
@EnableFeignClients
public class YourApplication {
public static void main(String[] args) {
SpringApplication.run(YourApplication.class, args);
}
}
调用发起方服务A定义调用服务B的通信接口
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(name = "serviceB", url = "http://localhost:8081")
public interface ServiceBFeignClient {
@GetMapping("/api/data")
String getDataFromServiceB();
}
使用@FeignClient注解来指定Feign客户端的名称和服务的URL。
name属性指定了客户端的名称(配置成在注册中心注册的名字)
url属性指定了服务的URL(url一般用于调试,可以手动指定调用的地址,如果使用注册中心使用name指定注册的名字即可,不用配置url)。如果服务没有跟服务发现框架(如nacos,Eureka)集成,可以使用url来指定调用的地址
服务端
原理
当应用启动时,Feign会根据接口定义自动生成一个代理对象。这个代理对象实现了接口中定义的方法,并将方法调用转换为HTTP请求。
当你调用代理对象的方法时,Feign会将方法调用转换为HTTP请求,并发送给目标服务。Feign使用底层的HTTP客户端(如OkHttp或HttpClient)来发送请求。
目标服务接收到请求后,会处理请求并返回响应。Feign会将响应转换为相应的Java对象,并返回给调用方。
@EnableFeignClients说明
定义在服务的调用方的启动上,这个注解告诉Spring Boot应用程序扫描并创建Feign客户端接口的代理实现类,以便进行服务调用。
被调用方的服务启动类型不需要指定
@FeignClient说明
用在调用方的feign接口上,为了被feign扫描程序发现并创建代理实现类
name指定注册中心中服务的名字
url指定要调用的服务地址
优先级:url>name
指定了url属性,Feign将直接使用该URL地址进行服务调用,而不会进行服务发现。
feign通过网关调用
要使用网关进行服务调用,你需要将Feign客户端的URL配置为网关的URL,并在网关中配置相应的路由规则。这样,当你使用Feign调用服务时,请求将经过网关进行路由和负载均衡。
feign对于http连接池的使用
从Feign的版本1.5.0开始,默认使用Apache HttpClient(具备连接池的功能)作为底层的HTTP客户端。在此之前的版本中,默认使用的是URLConnection(没有连接池)作为底层的HTTP客户端。
如下可以看到默认使用的httpClient
配置方式:
如果采用URLConnection的配置方式:
feign.client.default.connect-timeout 默认10s
feign.client.default.read-timeout 默认60s
如果采用Apache HttpClient的配置方式:
feign.httpclient.connection-timeout 连接超时时间默认2秒
feign.httpclient.time-to-live 存活时间默认900秒
feign.httpclient.max-connections 最大连接数默认200
如下可以看到默认的配置值
如果采用OkHttp配置方式:
feign.httpclient.connection-timeout 默认2秒
feign.client.default.read-timeout 默认60s
feign.httpclient.time-to-live 默认900秒
Apache HttpClient的默认连接池配置如下:
- 最大连接数(maxTotal):默认为200,表示最大同时可以建立的连接数。
- 每个路由的最大连接数(defaultMaxPerRoute):默认为20,表示对于每个目标主机的最大连接数限制。
- 连接的存活时间(keepAliveTime):默认为无限制,即连接可以一直保持活动状态。
如果你希望自定义Feign的连接池配置,可以通过创建一个HttpClient的Bean,并在该Bean中配置连接池的相关参数。以下是一个示例:
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
@Bean
public CloseableHttpClient httpClient() {
return HttpClientBuilder.create()
.setMaxConnTotal(100) // 设置最大连接数
.setMaxConnPerRoute(20) // 设置每个路由的最大连接数
.build();
}
}
在Feign客户端接口上使用@Configuration注解来指定使用自定义的连接池配置:
@FeignClient(name = "example", configuration = FeignConfig.class)
public interface ExampleClient {
// 接口方法定义
}
如果你使用的是其他的HTTP客户端,例如OkHttp,那么连接池的配置方式可能会有所不同。你可以根据具体的HTTP客户端文档来了解如何配置连接池。
重试说明
默认feign的重试机制的关闭的
如果要开启重试
添加依赖:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
配置重试策略:
全局重试配置(如果所有feign接口都要重试就配置这个)在你的应用程序的配置类中,创建一个Retryer的Bean,并配置重试策略。以下是一个示例:
import feign.Retryer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
@Bean
public Retryer feignRetryer() {
return new Retryer.Default(1000, 3000, 3); // 最大重试次数为3,初始间隔为1000毫秒,最大间隔为3000毫秒
}
}
部分重试配置(只对部分接口进行设置重试就配置这个),使用了@Retryable注解来定义重试策略。maxAttempts属性指定了最大重试次数,backoff属性指定了重试的间隔时间。
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.retry.annotation.Retryable;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(name = "example")
public interface ExampleFeignClient {
@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 1000, maxDelay = 3000))
@GetMapping("/example")
String getExample();
}
启用重试机制:在Feign客户端接口上使用@EnableRetry注解来启用重试机制。以下是一个示例:
-
java concurrent包总结
简介 concurrent:并发 JUC:java.util....
-
java Cookie和Session
什么是会话?它可以解决什么问题? 会话可简单理解为:用户开一...
-
java EL表达式
EL表达式 1.什么是EL表达式 EL是Expression La...
-
java mybatis-plus总结
说明 是一个 Mybatis 的增强工具,它已经封装好了一些cr...
-
java Lombok总结
注解说明 @Data 标注在实体类上,不用写set和get方法,...
-
java Swagger总结
Swagger说明 swagger是当下比较流行的实时接口文文...