SpringCloud OpenFeign
1.OpenFeign 介绍
1.OpenFeign 是什么
-
OpenFeign 是个声明式 WebService 客户端,使用 OpenFeign 让编写 Web Service 客户端 更简单 -
它的使用方法是定义一个服务接口然后在上面添加注解 -
OpenFeign 也支持可拔插式的编码器和解码器。 -
Spring Cloud 对 OpenFeign 进 行 了 封 装 使 其 支 持 了 Spring MVC 标 准 注 解 和 HttpMessageConverters -
OpenFeign 可以与 Eureka 和 Ribbon 组合使用以支持负载均衡
2.官网
地址:openFeign官网
3.Feign 和 OpenFeign 区别
Feign
1.Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端 2.Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。
3.Feign的使用方式是:使用Feign的注解定义接口,调用服务注册中心的服务
4.Feign支持的注解和用法请参考官方文档:https://github.com/OpenFeign/feign
5.Feign本身不支持Spring MVC的注解,它有一套自己的注解
6.引入依赖
<dependencies>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-bom</artifactId>
<version>??feign.version??</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
OpenFeign
1.OpenFeign是Spring Cloud 在Feign的基础上支持了Spring MVC的注解,如 @RequesMapping等等。
2.OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口
3.OpenFeign通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务
4.引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
精简一句话:OpenFeign 就是在 Feign 基础上做了加强 , 有些程序员为了方便,说 Feign 就是指的 OpenFeign
2.OpenFeign-应用实例
1.需求分析/图解
– 示意图
2.创建服务消费模块 -通过 OpenFeigen 实现远程调用的三种方式
1.通过注册中心服务发现实现远程调用
1.参考 member-service-consumer-80 创建 member-service-consumer-openfeign-80模块
2.修改 pom.xml,引入openfeign依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
3.创建 application.yml 内容如下:
server:
port: 80
spring:
application:
name: member-service-consumer-openfeign-80
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka9001.com:9001/eureka/,http://eureka9002.com:9002/eureka/
4.创建主启动类
@EnableFeignClients
@EnableEurekaClient
@SpringBootApplication
public class MemberConsumerOpenfeignApplication {
public static void main(String[] args) {
SpringApplication.run(MemberConsumerOpenfeignApplication.class,args);
}
}
5.创建MemberFeignService.java,
@Component
@FeignClient(value = "MEMBER-SERVICE-PROVIDER")
public interface MemberFeignService {
@GetMapping("/member/get/{id}")
Result getMemberById(@PathVariable("id") Long id);
}
6.创建MemberConsumerFeignController.java
@RestController
@RequiredArgsConstructor
public class MemberConsumerFeignController {
private final MemberFeignService memberFeignService;
@GetMapping(value = "/member/consumer/openfeign/get/{id}")
public Result getMemberById(@PathVariable("id") Long id) {
return memberFeignService.getMemberById(id);
}
}
7.启动测试
openfeign默认轮询的方式实现负载均衡
2.指定url地址,不经过Ribbon的服务选择,直接请求服务
@Component
@FeignClient(name = "member",url = "192.168.79.1:10001")
public interface MemberFeignService {
@GetMapping("/member/get/{id}")
Result getMemberById(@PathVariable("id") Long id);
}
3.动态url地址,不经过Ribbon的服务选择,直接请求服务
@FeignClient(name = "member",url = "${member-provider.requesturl:}",contextId = "dynamicUrl")
@Component
public interface MemberFeignDynamicUrlService {
@GetMapping("/member/get/{id}")
Result getMemberById(@PathVariable("id") Long id);
}
3.OpenFeign-日志配置
1.基本介绍
-
说明: Feign 提供了日志打印功能,可以通过配置来调整日志级别,从而对 Feign 接口的 调用情况进行监控和输出 -
日志级别
NONE∶默认的,不显示任何日志 BASIC∶仅记录请求方法、URL、响应状态码及执行时间;
HEADERS∶除了 BASIC中定义的信息之外,还有请求和响应的头信息;
FULL∶除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据。
2.配置日志-应用实例
1.创建配置类
@Configuration
public class OpenFeignConfig {
@Bean
public Logger.Level logLevel(){
return Logger.Level.FULL;
}
}
2.修改yml文件,指定openfeign日志级别
logging:
level:
com.llp.springcloud.service.MemberFeignService: debug
3.启动测试
[MemberFeignService#getMemberById]
2022-09-08 21:28:18.980 DEBUG 25628 --- [p-nio-80-exec-1] c.l.s.service.MemberFeignService : [MemberFeignService#getMemberById] {"code":"200","msg":"查询会员成功member-service-provider-10000","data":{"id":1,"name":"smith","pwd":"202cb962ac59075b964b07152d234b70","mobile":"123456789000","email":"smith@sohu.com","gender":1}}
2022-09-08 21:28:18.980 DEBUG 25628 --- [p-nio-80-exec-1] c.l.s.service.MemberFeignService : [MemberFeignService#getMemberById] <--- END HTTP (202-byte body)
4.OpenFeign-超时时间配置
1.先看一个问题
1.src\main\java\com\llp\springcloud\controller\MemberController.java新增一个测试超时的方法
@GetMapping(value = "/member/timeout")
public Result timeout() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return Result.success();
}
2.修改src\main\java\com\llp\springcloud\service\MemberFeignService.java
@GetMapping(value = "/member/timeout")
Result timeout();
3.member-service-provider-10000、member-service-provider-10002两个服务端添加对应的模拟超时的方法
@GetMapping(value = "/member/timeout")
public Result timeout() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return Result.success();
}
4.访问测试
openfeign默认超时时间为1秒,即调用得到响应的时间超出1秒则会超时抛出异常
2.设置超时时间
1.设置Ribbon的超时时间(不推荐)
设置很简单,在配置文件中添加如下设置:
ribbon:
ReadTimeout: 5000
ConnectionTimeout: 5000
2.设置openFeign的超时时间(推荐)
openFeign设置超时时间非常简单,只需要在配置文件中配置,如下:
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
再次测试
default设置的是全局超时时间,对所有的openFeign接口服务都生效
但是正常的业务逻辑中可能涉及到多个openFeign接口的调用,如下图:
那么上面配置的全局超时时间能不能通过呢?很显然是serviceA、serviceB能够成功调用,但是serviceC并不能成功执行,肯定报超时。
此时我们可以给serviceC这个服务单独配置一个超时时间,配置如下:
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
serviceC:
connectTimeout: 30000
readTimeout: 30000
这样A、B两个服务的超时时间就是50s,而C服务的超时时间就是30s了
5.OpenFeign-指定公共请求参数
1.创建FeignRequestHeaderInterceptor.java
@Slf4j
@RequiredArgsConstructor
public class FeignRequestHeaderInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
try {
Date currentTime = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.ENGLISH);
String date = simpleDateFormat.format(currentTime);
requestTemplate.header("Date", date);
requestTemplate.header("Address", "00000");
} catch (Exception e) {
log.error("会话Authorization异常", e);
}
}
}
2.在openfeign接口中指定配置类
@Component
@FeignClient(value = "MEMBER-SERVICE-PROVIDER",configuration = {FeignRequestHeaderInterceptor.class})
public interface MemberFeignService {
@GetMapping("/member/get/{id}")
Result getMemberById(@PathVariable("id") Long id);
@GetMapping(value = "/member/timeout")
Result timeout();
}
6.OpenFeign发送Https请求如何忽略SSL证书认证
? 我们在使用opefeign框架去发送Https请求调用服务器接口时,如果服务器没有证书或者证书过期,但还是要https去调用,我们可以直接绕过SSL证书认证,否则就可能出现SSLHandshakeException异常情况,那么我们该如何使OpenFeign绕过SSL验证呢?
FeginClient作为一个http请求工具,用来调用第三方接口,但是由于第三方接口常常是https开头,导致在调用的时候,触发SSL安全认证,这时候也就可以使用绕过认证的方法。
这里我们就以Springcloud项目整合OpenFeign框架为例,我们只需将Feign的配置类修改如下即可:
@Configuration
public class FeignConfiguration {
@Bean
public CachingSpringLoadBalancerFactory cachingFactory(SpringClientFactory clientFactory) {
return new CachingSpringLoadBalancerFactory(clientFactory);
}
@Bean
@ConditionalOnMissingBean
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
SpringClientFactory clientFactory) throws NoSuchAlgorithmException, KeyManagementException {
SSLContext ctx = SSLContext.getInstance("SSL");
X509TrustManager tm = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
ctx.init(null, new TrustManager[]{tm}, null);
return new LoadBalancerFeignClient(new Client.Default(ctx.getSocketFactory(),
(hostname, session) -> true),
cachingFactory, clientFactory);
}
}
更多细节可以参考:OpenFeign介绍和使用注意
|