SpringCloud OpenFeign
1.OpenFeign 介绍
1.OpenFeign 是什么
-
OpenFeign 是个声明式 WebService 客户端,使用 OpenFeign 让编写 Web Service 客户端 更简单
-
它的使用方法是定义一个服务接口然后在上面添加注解
-
OpenFeign 也支持可拔插式的编码器和解码器。
-
Spring Cloud 对 OpenFeign 进 行 了 封 装 使 其 支 持 了 Spring MVC 标 准 注 解 和 HttpMessageConverters
-
OpenFeign 可以与 Eureka 和 Ribbon 组合使用以支持负载均衡
地址: openFeign官网
3.Feign 和 OpenFeign 区别
Feign
1.Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端 2.Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。
3.Feign的使用方式是:使用Feign的注解定义接口,调用服务注册中心的服务
4.Feign本身不支持Spring MVC的注解,它有一套自己的注解
5.引入依赖
<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依赖
<!--引入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 eureka: client: #将自己注册到eureka-server register-with-eureka: true #表示从eureka-server获取注册信息 #如果是单节点是可以不配置的,但如果是集群则必须配置为true,才能配合Ribbon实现负载均衡功能 fetch-registry: true service-url: #表示将自己注册到哪个eureka-server defaultZone: http://eureka9001.com:9001/eureka/,http://eureka9002.com:9002/eureka/
4.创建主启动类
//启用OpenFeignClient @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 { //定义方法-远程调用接口 /** * 1. 远程调用的方式是get * 2. 远程调用的url http://MEMBER-SERVICE-PROVIDER/member/get/{id} * 3. MEMBER-SERVICE-PROVIDER 就是服务提供方在Eureka Server 注册的服务 * 4. openfeign 会根据负载均衡来决定调用10000/10002-默认是轮询 * 5. 因为openfeign 好处是支持了springmvc注解 + 接口解耦 * * openfeign是怎么样去远程调用的呢? * 1.注册中心通过MEMBER-SERVICE-PROVIDER服务注册名从注册中心去获取请求地址 * 192.168.79.1:member-service-provider:10002 , 192.168.79.1:member-service-provider:10001 * 2.通过springmvc注解 + 接口的方式实现远程调用 * 3.openfeign接口地址需要和远程调用服务的地址一致 */ @GetMapping("/member/get/{id}") Result getMemberById(@PathVariable("id") Long id); }
6.创建MemberConsumerFeignController.java
@RestController @RequiredArgsConstructor public class MemberConsumerFeignController { //装配MemberFeignService 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 /** * 指定远程调用url,用于固定访问某个服务不经过注册中心做服务的发现 * value 和 name 的作用一样,如果没有配置url那么配置的值将作为服务名称,用于服务发现。反之只是一个名称。 */ @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的服务选择,直接请求服务
/** * 1.指定远程调用url,用于固定访问某个服务不经过注册中心做服务的发现 * 2.value 和 name 的作用一样,如果没有配置url那么配置的值将作为服务名称,用于服务发现。反之只是一个名称。 * 3.contextId 当name/value相同时,指定不同的id来做区别 * 也可以通过配置spring.main.allow-bean-definition-overriding=true来解决名称冲突的问题 * 4.${member-provider.requesturl:} 从yml配置文件中读取 */ @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, OpenFeign全局日志配置 @Configuration public class OpenFeignConfig { /** * 指定日志级别 * @return */ @Bean public Logger.Level logLevel(){ return Logger.Level.FULL; } }
2.修改yml文件,指定openfeign日志级别
logging: # openfeign接口远程调用过程打印信息 级别-Debug 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新增一个测试超时的方法
/** * 测试openfeign超时,默认1秒 * @return */ @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
/** * 测试openfeign超时 * @return */ @GetMapping(value = "/member/timeout") Result timeout();
3.member-service-provider-10000、member-service-provider-10002两个服务端添加对应的模拟超时的方法
/** * 测试openfeign超时,默认1秒 * @return */ @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: #1. 设置feign客户端超时时间(openfeign默认支持ribbon) #2. ReadTimeout: 5000: 建立连接从服务提供方获取可用资源的所用的全部时间 #3. 时间单位是毫秒 ReadTimeout: 5000 #两端连接所用时间 ConnectionTimeout: 5000
2.设置openFeign的超时时间(推荐)
openFeign设置超时时间非常简单,只需要在配置文件中配置,如下:
feign: client: config: ## default 设置的全局超时时间,指定服务名称可以设置单个服务的超时时间 default: connectTimeout: 5000 readTimeout: 5000
再次测试
default设置的是全局超时时间,对所有的openFeign接口服务都生效
但是正常的业务逻辑中可能涉及到多个openFeign接口的调用,如下图:
那么上面配置的全局超时时间能不能通过呢?很显然是serviceA、serviceB能够成功调用,但是serviceC并不能成功执行,肯定报超时。
此时我们可以给serviceC这个服务单独配置一个超时时间,配置如下:
feign: client: config: ## default 设置的全局超时时间,指定服务名称可以设置单个服务的超时时间 default: connectTimeout: 5000 readTimeout: 5000 ## 为serviceC这个服务单独配置超时时间 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"); //requestTemplate.body(); } catch (Exception e) { log.error("会话Authorization异常", e); } } }
2.在openfeign接口中指定配置类
@Component //configuration是配置Feign配置类,在配置类中可以自定义Feign的Encoder、Decoder、LogLevel、Contract等。 @FeignClient(value = "MEMBER-SERVICE-PROVIDER",configuration = { FeignRequestHeaderInterceptor.class}) public interface MemberFeignService { //定义方法-远程调用接口 /** * 1. 远程调用的方式是get * 2. 远程调用的url http://MEMBER-SERVICE-PROVIDER/member/get/{id} * 3. MEMBER-SERVICE-PROVIDER 就是服务提供方在Eureka Server 注册的服务 * 4. openfeign 会根据负载均衡来决定调用10000/10002-默认是轮询 * 5. 因为openfeign 好处是支持了springmvc注解 + 接口解耦 * <p> * openfeign是怎么样去远程调用的呢? * 1.注册中心通过MEMBER-SERVICE-PROVIDER服务注册名从注册中心去获取请求地址 * 192.168.79.1:member-service-provider:10002 , 192.168.79.1:member-service-provider:10001 * 2.通过springmvc注解 + 接口的方式实现远程调用 * 3.openfeign接口地址需要和远程调用服务的地址一致 */ @GetMapping("/member/get/{id}") Result getMemberById(@PathVariable("id") Long id); /** * 测试openfeign超时 * @return */ @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 new X509Certificate[0] return null; } }; ctx.init(null, new TrustManager[]{ tm}, null); return new LoadBalancerFeignClient(new Client.Default(ctx.getSocketFactory(), (hostname, session) -> true), cachingFactory, clientFactory); } }
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/94757.html