站长工具官网,烟台互联网公司有哪些,开发软件平台,带佣金的旅游推广平台有哪些OpenFeign服务接口调用
1、OpenFeign简介
Feign是一个声明性web服务客户端。它使编写web服务客户端变得更容易。使用Feign创建一个接口并对其进行注释。它具有可插入的注释支持#xff0c;包括Feign注释和JAX-RS注释。Feign还支持可插拔编码器和解码器。Spring Cloud添加…OpenFeign服务接口调用
1、OpenFeign简介
Feign是一个声明性web服务客户端。它使编写web服务客户端变得更容易。使用Feign创建一个接口并对其进行注释。它具有可插入的注释支持包括Feign注释和JAX-RS注释。Feign还支持可插拔编码器和解码器。Spring Cloud添加了对Spring MVC注释的支持以及对使用Spring Web中默认使用的HttpMessageConverter的支持。Spring Cloud集成了Eureka、Spring Cloud CircuitBreaker以及Spring Cloud LoadBalancer以便在使用Feign时提供负载平衡的http客户端。
官网Spring Cloud OpenFeign
一句话openfeign是一个声明式的Web服务客户端我们只需要创建一个Rest接口并在该接口上添加注解FeignClint即可使用OpenFeign基本上就是当前微服务之间调用的事实标准。
官网演示了一个案例 先在springboot应用中开启FeignClients SpringBootApplication
EnableFeignClients
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}}然后写个接口StoreClient打上FeignClint注解 FeignClient(stores)
public interface StoreClient {RequestMapping(method RequestMethod.GET, value /stores)ListStore getStores();RequestMapping(method RequestMethod.GET, value /stores)PageStore getStores(Pageable pageable);RequestMapping(method RequestMethod.POST, value /stores/{storeId}, consumes application/json)Store update(PathVariable(storeId) Long storeId, Store store);RequestMapping(method RequestMethod.DELETE, value /stores/{storeId:\\d})void delete(PathVariable Long storeId);
}2、OpenFeign能干什么
前面在使用SpringCloud LoadBalancerRestTemplate时利用RestTemplate对http请求的封装处理形成了一套模版化的调用方法。
但是在实际开发中由于对服务依赖的调用可能不止一处往往一个接口会被多处调用所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。
所以OpenFeign在此基础上做了进一步封装由他来帮助我们定义和实现依赖服务接口的定义。 在OpenFeign的实现下我们只需创建一个接口并使用注解的方式来配置它(在一个微服务接口上面标注一个**FeignClient**注解即可)即可完成对服务提供方的接口绑定统一对外暴露可以被调用的接口方法大大简化和降低了调用客户端的开发量也即由服务提供者给出调用接口清单消费者直接通过OpenFeign调用即可。
OpenFeign同时还集成SpringCloud LoadBalancer
可以在使用OpenFeign时提供Http客户端的负载均衡也可以集成阿里巴巴Sentinel来提供熔断、降级等功能。而与SpringCloud LoadBalancer不同的是通过OpenFeign只需要定义服务绑定接口且以声明式的方法优雅而简单的实现了服务调用。
OpenFeign主要能干的事
可插拔的注解支持包括Feign注解和JAX-RS注解支持可插拔的HTTP编码器和解码器支持Sentinel和它的Fallback支持SpringCloudLoadBalancer的负载均衡支持HTTP请求和响应的压缩
我们目前是80消费者端的服务去调8001支付服务模块和8002订单服务模块在80消费者端我们使用的是RestTemplate实现调用但是微服务之间也需要相互调用呢8002调用8001呢难不成每一个微服务想调用其他服务时再写一次RestTemplate8001作为一个支付服务含有很多支付流水信息会有很多其他微服务会调用它根据解耦和面向接口的原则我们最好在8001上写出对外暴露的接口其他服务想调用它就要找8001定义的接口。
3、使用
架构说明图 3.1、新建module
新建modulecloud-consumer-feign-order80导入依赖。
pom.xml dependencies!--openfeign新加的坐标--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependency!--SpringCloud consul discovery--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-consul-discovery/artifactId/dependency!-- 引入自己定义的api通用包 --dependencygroupIdcom.zm.cloud/groupIdartifactIdcloud-api-commons/artifactIdversion1.0-SNAPSHOT/version/dependency!--web actuator--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependency!--lombok--dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependency!--hutool-all--dependencygroupIdcn.hutool/groupIdartifactIdhutool-all/artifactId/dependency!--fastjson2--dependencygroupIdcom.alibaba.fastjson2/groupIdartifactIdfastjson2/artifactId/dependency!-- swagger3 调用方式 http://你的主机IP地址:5555/swagger-ui/index.html --dependencygroupIdorg.springdoc/groupIdartifactIdspringdoc-openapi-starter-webmvc-ui/artifactId/dependency/dependenciesbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build 写YML
server:port: 80
spring:application:name: cloud-consumer-openfeign-order####Spring Cloud Consul for Service Discoverycloud:consul:host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name} 主启动类
SpringBootApplication
EnableDiscoveryClient //使用consul为注册中心时注册服务
EnableFeignClients //开启OpenFeign功能并激活
public class MainOpenFeign80 {public static void main(String[] args) {SpringApplication.run(MainOpenFeign80.class,args);}
} 要把接口PayFeignApi创建在通用的api模块cloud-api-commons中
修改cloud-api-commons模块pom文件中添加openfeign的依赖
!--openfeign--
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId
/dependency 参考微服务8001的Controller层新建PayFeignApi接口
FeignClient(value cloud-payment-service)
public interface PayFeignApi {/*** 新增一条支付相关流水记录* param payDTO* return*/PostMapping(/pay/add)public ResultData addPay(RequestBody PayDTO payDTO);//通过id查询GetMapping(value /pay/get/{id})public ResultData getPayById(PathVariable(id) Integer id);//删除DeleteMapping(/pay/del/{id})public ResultData delById(PathVariable(id) Integer integer);//修改PutMapping(/pay/update)public ResultData update(RequestBody PayDTO payDTO);//查全部GetMapping(/pay/getall)public ResultData getAll();//openfeign天然支持负载均衡演示GetMapping(/pay/getInfo)public String myLB();} 我们把原来微服务80的controller复制一份到cloud-consumer-feign-order80中原来的内容全部删除重新使用PayFeignApi实现。当应用启动时Feign 使用 Java 的动态代理机制生成接口的实现。这个过程由 Spring Cloud 集成提供支持Feign 客户端在内部构建了请求的详细信息并将接口方法调用转换为 HTTP 调用。
RestController
public class OrderController {Resourceprivate PayFeignApi payFeignApi;PostMapping(/feign/pay/add)public ResultData addPay(RequestBody PayDTO payDTO){System.out.println(1、使用本地addOrder新增订单功能(省略sql操作),2、开启addPay支付微服务远程调用);ResultData resultData payFeignApi.addPay(payDTO);return resultData;}GetMapping(/feign/pay/get/{id})public ResultData getByID(PathVariable(id) Integer id){System.out.println(-------支付微服务远程调用按照id查询订单支付流水信息);ResultData payById payFeignApi.getPayById(id);return payById;}DeleteMapping(/feign/pay/del/{id})public ResultData delById(PathVariable(id) Integer id){System.out.println(-------支付微服务远程调用按照id查删除订单支付流水信息);return payFeignApi.delById(id);}PutMapping(/feign/pay/update)public ResultData update(RequestBody PayDTO payDTO){System.out.println(-------支付微服务远程调用修改订单支付流水信息);return payFeignApi.update(payDTO);}GetMapping(/feign/pay/getall)public ResultData getAll(){return payFeignApi.getAll();}GetMapping(/feign/pay/getInfo)public String mylb(){return payFeignApi.myLB();}} 测试启动新的80服务启动微服务8001和8002. 使用浏览器或者其他测试工具先查询一个看看 添加一个数据 查询全部 删除刚才新增的 下面测试负载均衡 因为OpenFeign默认的集成了LoadBalancer所以就会负载均衡。
梳理一遍 在使用Feign进行微服务间的通信时当发出一个请求到PayFeignApi接口时该请求实际上是通过Feign客户端进行代理的。Feign会根据你提供的FeignClient(value cloud-payment-service)注解中的value值即服务名来定位目标服务。
当请求到达PayFeignApi接口时大致流程
路由到目标服务Feign会根据我们在注解上填的微服务名称去注册中心consul找有没有这个微服务然后找到这个微服务下的具体示例列表因为Feign本身就有负载均衡能力默认还是轮询的方式进行调度。选择具体的端点选择完目标示例之后Feign会根据你定义的路径/pay/add来拼凑完整的URL比如说选择了8001那么URL就是http://localhost:8001/pay/add发送请求URL拿到后Feign就使用HTTP客户端发送请求到服务提供者然后就是具体的处理请求了至此整个服务流程完成。
4、OpenFeign高级特性
4.1、OpenFeign超时控制
在Spring Cloud微服务架构中大部分公司都是利用OpenFeign进行服务间的调用而比较简单的业务使用默认配置是不会有多大问题的但是如果是业务比较复杂服务要进行比较繁杂的业务计算那后台很有可能会出现Read Timeout这个异常因此定制化配置超时时间就有必要了。 4.1.1、设置超时演示
我们故意设置超时出错情况让8001的服务睡一会儿。
服务提供方cloud-provider-payment8001故意写暂停62秒钟程序把getById的controller修改一下睡一会儿
//通过id查询
GetMapping(/pay/get/{id})
Operation(summary 查询,description 通过ID查询)
public ResultDataPay payById(PathVariable(id) Integer id){System.out.println(---------正在查询--------);try {TimeUnit.SECONDS.sleep(62);} catch (InterruptedException e) {throw new RuntimeException(e);}return ResultData.success(payServiceImp.getById(id));
} 为啥是62秒试出超时时间。
服务调用方cloud-consumer-feign-order80写好捕捉超时异常
GetMapping(/feign/pay/get/{id})
public ResultData getByID(PathVariable(id) Integer id){System.out.println(-------支付微服务远程调用按照id查询订单支付流水信息);ResultData payById null;try {System.out.println(调用开始时间------ DateUtil.now());payById payFeignApi.getPayById(id);}catch (Exception e){e.printStackTrace();System.out.println(调用结束时间------ DateUtil.now());ResultData.fail(ReturnCodeEnum.RC500.getCode(), e.getMessage());}return payById;
} 开始测试重新启动8001和80浏览器输入localhost/feign/pay/get/1
**注意**如果测试的时候你的8002服务没有关闭的话轮询还是存在的可能第一次请求就是成功的刷新一下就轮到8001了你要不想轮询就把8002关闭。 所以说OpenFeign的默认超时时间是60秒所以故意弄的睡眠时间就是60秒以上。
默认OpenFeign客户端等待60秒钟但是服务端处理超过规定时间会导致Feign客户端返回报错。
为了避免这样的情况有时候我们需要设置Feign客户端的超时控制默认60秒太长或者业务时间太短都不好。
这就需要在yml中开始配置了
connectTimeout 连接超时时间readTimeout 请求处理超时时间 官网默认配置参数 全局配置
在application.yml文件中配置
server:port: 80
spring:application:name: cloud-consumer-openfeign-order####Spring Cloud Consul for Service Discoverycloud:consul:host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}openfeign:client:config:default:#连接超时时间connectTimeout: 3000#读取超时时间readTimeout: 3000 重启80服务测试一下 有1秒的误差打印信息了。
指定配置
还可以指定某个服务的超时时间但是不能和default一起写这样会覆盖掉default的时间用你指定服务的超时时间。演示一下两者都写的情况。
server:port: 80
spring:application:name: cloud-consumer-openfeign-order####Spring Cloud Consul for Service Discoverycloud:consul:host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}openfeign:client:config:default:connectTimeout: 3000 #连接超时时间readTimeout: 3000 #读取超时时间cloud-payment-service:connectTimeout: 5000readTimeout: 5000 再次测试 结果是5秒所以自己指点的时间就会覆盖掉默认设置的时间。
4.2、OpenFeign重试机制
OpenFeign的重试机制默认是关闭的 想开启重试就新增一个配置类FeignConfig并修改Retryer配置把指定的8001超时时间设置为4秒
Configuration
public class FeignConfig {Beanpublic Retryer myRetryer(){//return Retryer.NEVER_RETRY; //Feign默认配置是不走重试策略的//最大请求次数为12次初始时间间隔为100ms重试最大间隔时间为1秒return new Retryer.Default(100,1,3);}
} 现在测试一下如果走了重试应该就是5*315秒 4.3、OpenFeign默认HttpClient修改
OpenFeign中http client如果不做特殊配置OpenFeign默认使用JDK自带HttpURLConnection发送HTTP请求由于默认HttpURLConnection没有连接池、性能和效率比较低如果采用默认性能上不是最强大的所以需要换掉推荐使用阿帕奇的HC5。
我们看到官网 我们先把超时重试的配置关闭。
Configuration
public class FeignConfig {Beanpublic Retryer myRetryer(){return Retryer.NEVER_RETRY; //Feign默认配置是不走重试策略的//最大请求次数为12次初始时间间隔为100ms重试最大间隔时间为1秒//return new Retryer.Default(100,1,3);}
} 修改POM文件添加依赖
!-- httpclient5--
dependencygroupIdorg.apache.httpcomponents.client5/groupIdartifactIdhttpclient5/artifactIdversion5.3/version
/dependency
!-- feign-hc5--
dependencygroupIdio.github.openfeign/groupIdartifactIdfeign-hc5/artifactIdversion13.1/version
/dependency 在application.yml配置文件中打开Apache HttpClient5
server:port: 80
spring:application:name: cloud-consumer-openfeign-order####Spring Cloud Consul for Service Discoverycloud:consul:host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}openfeign:client:config:
# default:
# connectTimeout: 3000 #连接超时时间
# readTimeout: 3000 #读取超时时间cloud-payment-service:connectTimeout: 5000readTimeout: 5000httpclient:hc5:enabled: true 重启再看一下现在报错信息来至于哪里 4.4、OpenFeign请求/响应压缩
对请求和响应进行GZIP压缩
Spring Cloud OpenFeign支持对请求和响应进行GZIP压缩以减少通信过程中的性能损耗。
通过下面的两个参数设置就能开启请求与相应的压缩功能
spring.cloud.openfeign.compression.request.enabledtruespring.cloud.openfeign.compression.response.enabledtrue 细粒度化设置
对请求压缩做一些更细致的设置比如下面的配置内容指定压缩的请求数据类型并设置了请求压缩的大小下限只有超过这个大小的请求才会进行压缩
spring.cloud.openfeign.compression.request.enabledtruespring.cloud.openfeign.compression.request.mime-typestext/xml,application/xml,application/json #触发压缩数据类型spring.cloud.openfeign.compression.request.min-request-size2048 #最小触发压缩的大小 我们可以在配置文件中设置一下
server:port: 80
spring:application:name: cloud-consumer-openfeign-order####Spring Cloud Consul for Service Discoverycloud:consul:host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}openfeign:client:config:
# default:
# connectTimeout: 3000 #连接超时时间
# readTimeout: 3000 #读取超时时间cloud-payment-service:connectTimeout: 5000readTimeout: 5000httpclient:hc5:enabled: truecompression:request:enabled: truemin-request-size: 2048 #最小触发压缩的大小mime-types: text/xml,application/xml,application/json #触发压缩数据类型response:enabled: true 压缩效果在日志打印功能中展现…
4.5、OpenFeign日志打印功能
Feign 提供了日志打印功能我们可以通过配置来调整日志级别从而了解 Feign 中 Http 请求的细节说白了就是对Feign接口的调用情况进行监控和输出。
日志级别
NONE默认的不显示任何日志BASIC仅记录请求方法、URL、响应状态码及执行时间HEADERS除了 BASIC 中定义的信息之外还有请求和响应的头信息FULL除了 HEADERS 中定义的信息之外还有请求和响应的正文及元数据。
官网说明 我们在FeignConfig中可以配置日志注意导包要导feign的。
Configuration
public class FeignConfig {Beanpublic Retryer myRetryer(){return Retryer.NEVER_RETRY; //Feign默认配置是不走重试策略的//最大请求次数为12次初始时间间隔为100ms重试最大间隔时间为1秒//return new Retryer.Default(100,1,3);}BeanLogger.Level feignLoggerLevel() {return Logger.Level.FULL;}
} 然后在配置文件中开启日志的Feign客户端。
这里有一个套路可以这样写
公式(三段)logging.level 含有FeignClient注解的完整带包名的接口名debug完整的application.yml
server:port: 80
spring:application:name: cloud-consumer-openfeign-order####Spring Cloud Consul for Service Discoverycloud:consul:host: localhostport: 8500discovery:prefer-ip-address: true #优先使用服务ip进行注册service-name: ${spring.application.name}openfeign:client:config:
# default:
# connectTimeout: 3000 #连接超时时间
# readTimeout: 3000 #读取超时时间cloud-payment-service:connectTimeout: 5000readTimeout: 5000httpclient:hc5:enabled: truecompression:request:enabled: truemin-request-size: 2048 #最小触发压缩的大小mime-types: text/xml,application/xml,application/json #触发压缩数据类型response:enabled: true# feign日志以什么级别监控哪个接口
logging:level:com:zm:cloud:apis:PayFeignApi: debug 现在可以开始测试了重启服务测试。 我们可以看到开了压缩和没开压缩的还是有些差别的没开请求响应压缩看不到任何的请求响应信息。
重试机制控制台看到3次过程
现在有了日志打印功能就可以看到具体的3次重试过程了。
先把重试功能打开为了快速展示我们把超时时间改成1秒那么一会儿总时间应该是3秒。
Configuration
public class FeignConfig {Beanpublic Retryer myRetryer(){//return Retryer.NEVER_RETRY; //Feign默认配置是不走重试策略的//最大请求次数为12次初始时间间隔为100ms重试最大间隔时间为1秒return new Retryer.Default(100,1,3);}BeanLogger.Level feignLoggerLevel() {return Logger.Level.FULL;}
} 重启服务开始测试。