-
2022-04-26 20:26:41
1.pom文件
在pom文件中引入feign坐标
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
fegin服务需要注册在eureka上,才能调用eureka上的其他服务
2.配置文件
配置相应的eureka参数,将服务注册的eureka server上。
eureka: instance: prefer-ip-address: true client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://localhost:8761/eureka
3.添加注解
在启动类上添加相应的注解
@SpringBootApplication @EnableDiscoveryClient @EnableFeignClients(basePackages = {"com.example.feignclient1"}) ⇽--- feign接口所在的包目录,basePackages属性的值是一个数组,可以配置多个feign目录。开启feign的客户端 public class FeignClient1Application { public static void main(String[] args) { SpringApplication.run(FeignClient1Application.class, args); } }
4.feign接口示例
feign接口
@FeignClient(value = "EUREKA-CLIENT-1") public interface DeptFeignClient { @RequestMapping(method = RequestMethod.GET, path = "/dept/getListById", consumes = "application/json") RestDto<List<IdNameDto>> getDeptList(@RequestParam("id")String id); @RequestMapping(method = RequestMethod.POST, path = "/dept/queryByCriteria") RestDto<List<IdNameDto>> query(@RequestBody Criteria criteria); }
- @FeignClient(value = “EUREKA-CLIENT-1”) :此接口是一个feign接口,value值为被调用服务在eureka服务上的注册id,也就是该服务的服务名称。
- feign自动集成了ribbon,分布式服务默认使用轮询的策略。
5.代码示例
@Autowired private DeptFeignClient deptFeignClient; public List<IdNameDto> getOrgList(String id) throws Exception { RestDto<List<IdNameDto>> deptList = deptFeignClient.getDeptList(id); if (deptList.getResult().equals(0)){ return deptList.getData(); } else { throw new Exception("feign调用异常"); } }
结果展示
{ "code": "200", "result": 0, "msg": "操作成功", "data": [ { "id": "200", "name": "其他部门" } ] }
更多相关内容 -
OpenFeign动态URL测试Demo
2021-08-18 15:31:14使用OpenFeign进行服务端调用,动态修改URL的测试DEMO,该DEMO使用Maven进行创建,使用idea进行开发 -
带有OpenFeign的Spring-Cloud-Gateway:Hello World-具有OpenFeign的Spring Cloud Gateway
2021-02-17 09:01:57带有OpenFeign的Spring-Cloud-Gateway Spring Cloud Gateway + OpenFeign服务1服务2供应商MSA服务 실행 网关와Service1,Service2맞는맞는실행한실행한실행한 网关(8080) 服务1(10001) 服务2(10002) 하... -
spring cloud openfeign 源码实例解析
2020-08-25 13:02:20主要介绍了spring cloud openfeign 源码实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 -
spring boot openfeign从此和httpClient说再见详析
2020-08-27 09:01:25主要给大家介绍了关于spring boot openfeign从此和httpClient说再见的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧 -
spring-cloud-openfeign-core-3.1.1-API文档-中英对照版.zip
2022-05-04 11:34:39赠送jar包:spring-cloud-openfeign-core-3.1.1.jar; 赠送原API文档:spring-cloud-openfeign-core-3.1.1-javadoc.jar; 赠送源代码:spring-cloud-openfeign-core-3.1.1-sources.jar; 赠送Maven依赖信息文件:... -
Springcloud基于OpenFeign实现服务调用代码实例
2020-08-24 20:35:16主要介绍了Springcloud基于OpenFeign实现服务调用代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 -
Spring Cloud alibaba 集成 Sentinel openfeign nacos
2021-11-29 19:08:23配合博客https://blog.csdn.net/qq_42017523/article/details/121519054使用 -
SpringCloud 服务负载均衡和调用 Ribbon、OpenFeign的方法
2020-09-07 16:36:45主要介绍了SpringCloud 服务负载均衡和调用 Ribbon、OpenFeign的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下 -
Spring Cloud OpenFeign示例代码
2020-10-28 22:29:36springcloud openfeign 源码学习,springcloud openfeign 源码学习 -
SpringCloud-OpenFeign服务接口调用及代码
2021-06-01 13:45:06SpringCloud尚硅谷-OpenFeign服务接口调用及代码 -
OpenFeignDemo:OpenFeign演示
2021-05-09 23:58:32OpenFeign demo 服务间调用feign,在进行文件的传递会出现的情况 所使用的是spring boot 2.0 jdk是1.8 要进行pom文件的添加 spring boot 2.0 的feign依赖 <dependency><br> <groupId>org.springframework.cloud... -
springboot openfeign从JSON文件读取数据问题
2020-10-18 11:13:46今天主要说一下在openfeign里读取JSON文件的问题,我们将测试所需要的数据存储到文件里,在修改时关注点比较单纯 -
spring-cloud-openfeign-example:Spring Cloud OpenFeign的演示项目
2021-02-13 21:56:03春天的云openfeign示例 使用openfeign的继承特性,发现了一个问题。以本Demo的接口为例: com.example.controller.InheritProviderController.inherit()方法上没有继承到@GetMapping ,但是它为什么还能作为接口被... -
Spring Cloud alibaba 集成 Sentinel openfeign nacos seata
2021-12-06 19:41:00配合博客https://blog.csdn.net/qq_42017523/article/details/121648876使用 -
OpenFeign
2021-03-09 11:38:04OpenFeign是什么 Feign是一个声明式Web Service客户端。使用Feign能让编写Web Service客户端更加简单, 它的使用方法是定义一个接口,然后在上面添加注解,同时也支持JAX-RS标准的注解。Feign也支持可拔插式的编码器...OpenFeign是什么
Feign是一个声明式Web Service客户端。使用Feign能让编写Web Service客户端更加简单,
它的使用方法是定义一个接口,然后在上面添加注解,同时也支持JAX-RS标准的注解。Feign也支持可拔插式的编码器和解码器。Spring
Cloud对Feign进行了封装,使其支持了Spring
MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。Feign能干什么
Feign旨在使编写Java Http客户端变得更容易。
前面在使用Ribbon+RestTemplate时,利用RestTemplate对http请求的封装处理,形成了一套模版化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,我们只需创建一个接口并使用注解的方式来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可),即可完成对服务提供方的接口绑定,简化了使用Spring
cloud Ribbon时,自动封装服务调用客户端的开发量。Feign集成了Ribbon
利用Ribbon维护了Payment的服务列表信息,并且通过轮询实现了客户端的负载均衡。而与Ribbon不同的是,通过feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。
Feign和OpenFeign两者区别
Feign是Spring
Cloud组件中的一个轻量级RESTful的HTTP服务客户端Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务。<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>
OpenFeign是Spring
Cloud在Feign的基础上支持了SpringMVC的注解,如@RequesMapping等等。OpenFeign的@Feignclient可以解析SpringMVc的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
OpenFeign服务调用
- 主启动
package com.solo.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableFeignClients //开启Feign客户端 public class OrderFeignMain80 { public static void main(String[] args) { SpringApplication.run(OrderFeignMain80.class,args); } }
- 业务类接口
通过@FeignClient注解根据服务名称去调用具体的服务。
import com.solo.springcloud.entities.CommonResult; import com.solo.springcloud.entities.Payment; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @Service("service") @FeignClient(value = "CLOUD-PAYMENT-SERVICE") public interface PaymentFeignService { @GetMapping(value = "/payment/get/{id}") CommonResult<Payment> getPaymentById(@PathVariable("id") Long id); @GetMapping(value = "/payment/feign/timeout") public String paymentFeignTimeout(); }
OpenFeign超时控制
OpenFeign默认等待1秒钟,超过后报错。可以通过在配置文件中定义超时时间。
#设置feign客户端超时时间(OpenFeign默认支持ribbon)(单位:毫秒) ribbon: #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间 ReadTimeout: 5000 #指的是建立连接后从服务器读取到可用资源所用的时间 ConnectTimeout: 5000
OpenFeign日志增强
日志打印功能Feign提供了日志打印功能,我们可以通过配置来调整日恙级别,从而了解Feign 中 Http请求的细节。
说白了就是对Feign接口的调用情况进行监控和输出
日志级别
- NONE:默认的,不显示任何日志;
- BASIC:仅记录请求方法、URL、响应状态码及执行时间;
- HEADERS:除了BASIC中定义的信息之外,还有请求和响应的头信息;
- FULL:除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据。
配置日志bean
import feign.Logger; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FeignConfig { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } }
YML文件里需要开启日志的Feign客户端:
logging: level: # feign日志以什么级别监控哪个接口 com.solo.springcloud.services.PaymentFeignService: debug
-
SpringCloud.Honxton 版本 OpenFeign原理上篇
2020-12-21 23:52:35SpringCloud.Honxton 版本 OpenFeign原理前置说明如何使用openfeign原理总结 前置说明 好久没写博客了, 突然想起自己的springcloud系列文章就讲了配置中心,注册中心,负载均衡和熔断。那么今天就来分析一下... -
03_SpringCloud-openFeign远程调用.md
2020-01-03 14:03:41feign是一个客户端声明式http远程调用工具,提供了接口和注解方式进行调用 ,推荐使用feign继承体系方式进行内部RPC调用。 -
SpringCloud Alibaba使用(二) - sentinel fallback整合ribbon+openFeign 服务熔断功能 规则持久化.zip
2020-06-30 10:01:49SpringCloud Alibaba使用(二) - sentinel fallback整合ribbon+openFeign 服务熔断功能 规则持久化.zip -
11.OpenFeign之feign使用简介
2018-05-17 14:51:59Feign使用像Jersey和CXF这样的工具来编写Rest或SOAP服务的java客户端。此外,Feign允许您在诸如Apache HC这样的http库之上编写自己的代码。Feign将你的代码与http API连接起来,通过可定制的解码器和错误处理来将... -
openFeign
2021-10-06 18:41:132.Feign和openFeign有什么区别3.openFeign如何传参4.超时设置5.开启日志增强6.如何通讯优化7.如何熔断降级 1.Feign是什么? Feign集成了Ribbon、RestTemplate实现了负载均衡的执行Http调用,只不过对原有的方式...
文章目录
1.Feign是什么?
Feign集成了Ribbon、RestTemplate实现了负载均衡的执行Http调用,只不过对原有的方式(Ribbon+RestTemplate)进行了封装,开发者不必手动使用RestTemplate调服务,而是定义一个接口,在这个接口中标注一个注解即可完成服务调用,这样更加符合面向接口编程的宗旨,简化了开发。
2.Feign和openFeign有什么区别
3.openFeign如何传参
1、传递JSON数据
这个也是接口开发中常用的传参规则,在Spring Boot 中通过@RequestBody标识入参。@RestController @RequestMapping("/openfeign/provider") public class OpenFeignProviderController { @PostMapping("/order2") public Order createOrder2(@RequestBody Order order){ return order; } }
@FeignClient(value = "openFeign-provider") public interface OpenFeignService { /** * 参数默认是@RequestBody标注的,这里的@RequestBody可以不填 * 方法名称任意 */ @PostMapping("/openfeign/provider/order2") Order createOrder2(@RequestBody Order order); }
2、POJO表单传参
这种传参方式也是比较常用,参数使用POJO对象接收。@RestController @RequestMapping("/openfeign/provider") public class OpenFeignProviderController { @PostMapping("/order1") public Order createOrder1(Order order){ return order; } }
@FeignClient(value = "openFeign-provider") public interface OpenFeignService { /** * 参数默认是@RequestBody标注的,如果通过POJO表单传参的,使用@SpringQueryMap标注 */ @PostMapping("/openfeign/provider/order1") Order createOrder1(@SpringQueryMap Order order); }
3、URL中携带参数
此种方式针对restful方式中的GET请求,也是比较常用请求方式。@RestController @RequestMapping("/openfeign/provider") public class OpenFeignProviderController { @GetMapping("/test/{id}") public String test(@PathVariable("id")Integer id){ return "accept one msg id="+id; }
@FeignClient(value = "openFeign-provider") public interface OpenFeignService { @GetMapping("/openfeign/provider/test/{id}") String get(@PathVariable("id")Integer id); }
4、普通表单参数
此种方式传参不建议使用,但是也有很多开发在用。RestController @RequestMapping("/openfeign/provider") public class OpenFeignProviderController { @PostMapping("/test2") public String test2(String id,String name){ return MessageFormat.format("accept on msg id={0},name={1}",id,name); } }
@FeignClient(value = "openFeign-provider") public interface OpenFeignService { /** * 必须要@RequestParam注解标注,且value属性必须填上参数名 * 方法参数名可以任意,但是@RequestParam注解中的value属性必须和provider中的参数名相同 */ @PostMapping("/openfeign/provider/test2") String test(@RequestParam("id") String arg1,@RequestParam("name") String arg2); }
4.超时设置
1、设置Ribbon的超时时间(不推荐)
设置很简单,在配置文件中添加如下设置:ribbon: # 值的是建立链接所用的时间,适用于网络状况正常的情况下, 两端链接所用的时间 ReadTimeout: 5000 # 指的是建立链接后从服务器读取可用资源所用的时间 ConectTimeout: 5000
2、设置openFeign的超时时间(推荐)
openFeign设置超时时间非常简单,只需要在配置文件中配置,如下:feign: client: config: ## default 设置的全局超时时间,指定服务名称可以设置单个服务的超时时间 default: connectTimeout: 5000 readTimeout: 5000
5.开启日志增强
openFeign虽然提供了日志增强功能,但是默认是不显示任何日志的,不过开发者在调试阶段可以自己配置日志的级别。
openFeign的日志级别如下:
NONE:默认的,不显示任何日志;
BASIC:仅记录请求方法、URL、响应状态码及执行时间;
HEADERS:除了BASIC中定义的信息之外,还有请求和响应的头信息;
FULL:除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据。
配置起来也很简单,步骤如下:1、配置类中配置日志级别
2、yaml文件中设置接口日志级别logging: level: cn.myjszl.service: debug
6.如何通讯优化
gzip是一种数据格式,采用用deflate算法压缩数据;gzip是一种流行的数据压缩算法,应用十分广泛,尤其是在Linux平台。
GZIP
openFeign支持请求/响应开启GZIP压缩
openFeign开启GZIP
feign: ## 开启压缩 compression: request: enabled: true ## 开启压缩的阈值,单位字节,默认2048,即是2k,这里为了演示效果设置成10字节 min-request-size: 10 mime-types: text/xml,application/xml,application/json response: enabled: true
7.如何熔断降级
openFeign默认支持的就是Hystrix
但是阿里的Sentinel无论是功能特性、简单易上手等各方面都完全秒杀Hystrix,因此此章节就使用openFeign+Sentinel进行整合实现服务降级
1、添加Sentinel依赖
2、配置文件中开启sentinel熔断降级
3、添加降级回调类
4、添加fallback属性
8.如果feign的超时时间过了怎么办
报错
可以在yml上配置超时时间 -
OpenFeign 简单使用
2022-04-11 23:19:37文章目录一、源码简单分析1、导入依赖2、自动导入类3、OkHttpFeignLoadBalancedConfiguration 类4、DefaultFeignLoadBalancedConfiguration 类5、小结二 、OpenFeign 配置 Http 连接池1、配置 Apache httpclient ...文章目录
官方文档参考: https://docs.spring.io/spring-cloud-openfeign/docs/2.2.9.RELEASE/reference/html/,在 url 中选择自己对应的版本github 文档参考:https://github.com/OpenFeign/feign
一、源码简单分析
1、导入依赖
导入依赖 OpenFeign 依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
2、自动导入类
spring-cloud-starter-openfeign 引入了 spring-cloud-openfeign-core 依赖,查看 spring-cloud-openfeign-core/META-INF/spring.factories 自动加载 FeignRibbonClientAutoConfiguration 类
查看 FeignRibbonClientAutoConfiguration 类默认加载 DefaultFeignLoadBalancedConfiguration
3、OkHttpFeignLoadBalancedConfiguration 类
OkHttpFeignLoadBalancedConfiguration 类中可以看到 @ConditionalOnClass(OkHttpClient.class) 注解,如果没有 OkHttpClient 类则不加载 OkHttpFeignLoadBalancedConfiguration 类
@Configuration(proxyBeanMethods = false) @ConditionalOnClass(OkHttpClient.class) @ConditionalOnProperty("feign.okhttp.enabled") @Import(OkHttpFeignConfiguration.class) class OkHttpFeignLoadBalancedConfiguration { @Bean @ConditionalOnMissingBean(Client.class) public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory, okhttp3.OkHttpClient okHttpClient) { OkHttpClient delegate = new OkHttpClient(okHttpClient); return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory); } }
4、DefaultFeignLoadBalancedConfiguration 类
从源码可以看到没有注入 Client 相关的 bean ,则注入该 client
@Configuration class DefaultFeignLoadBalancedConfiguration { @Bean @ConditionalOnMissingBean public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) { return new LoadBalancerFeignClient(new Client.Default(null, null), cachingFactory, clientFactory); } }
查看 Client.Default 源码
public static class Default implements Client { public Response execute(Request request, Options options) throws IOException { HttpURLConnection connection = this.convertAndSend(request, options); return this.convertResponse(connection, request); } HttpURLConnection convertAndSend(Request request, Options options) throws IOException{ URL url = new URL(request.url()); HttpURLConnection connection = this.getConnection(url); } public HttpURLConnection getConnection(URL url) throws IOException { return (HttpURLConnection)url.openConnection(); } }
从 Client.Default 源码可以看到每次请求都建立一个新的 HttpURLConnection 连接
其他
HttpClientFeignLoadBalancedConfiguration.class, OkHttpFeignLoadBalancedConfiguration.class, HttpClient5FeignLoadBalancedConfiguration.class
类似5、小结
综上,默认情况下,spring cloud 没有引入 ApacheHttpClient 类(feign-httpclient jar包)和 okhhtp 类(okhttp jar包)和 ApacheHttp5Client ( ApacheHttp5Client jar 包) 类,所以默认使用 HttpURLConnection。
二 、OpenFeign 配置 Http 连接池
默认情况下,服务间调用使用 HttpURLConnection,效率比较低,可以通过连接池提高效率。
1、配置 Apache httpclient 连接池
pom.xml 中引入 feign-httpclient 依赖
<dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> </dependency>
bootstrap.yml 中添加配置
feign: httpclient: enabled: true hc5: enabled: false okhttp: enabled: false
简单配置如上即可,其他相关配置可使用默认值,详细配置可参考 FeignHttpClientProperties、FeignAutoConfiguration 类
HttpClient 默认配置如下,详细配置可参考 https://docs.spring.io/spring-cloud-openfeign/docs/2.2.9.RELEASE/reference/html/appendix.htmlfeign: httpclient: enabled: true hc5: enabled: false disable-ssl-validation: false # 禁用 SSL 验证 max-connections: 200 # 最大连接 max-connections-per-route: 50 # 路由最大连接数 time-to-live: 900 # 连接存活时间 time-to-live-unit: seconds # 连接存活时间单位 follow-redirects: true # 重定向 connection-timeout: 2000 # 连接超时 connection-timer-repeat: 3000 # 连接重复间隔 okhttp: enabled: false
2、配置 OkHttpClient 连接池
pom.xml 中引入 feign-okhttp 依赖
<dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-okhttp</artifactId> </dependency>
bootstrap.yml 中添加配置,其他详细配置参考上面的 Apache httpclient 连接池配置
feign: httpclient: enabled: false hc5: enabled: false okhttp: enabled: true
三、OpenFeign 简单测试
1、SPRING-CLOUD-SERVICE-OPENFEIGN 服务 bootstrap.yaml 配置
server: port: 20004 spring: application: name: SPRING-CLOUD-SERVICE-OPENFEIGN cloud: nacos: server-addr: 127.0.0.1:8848 discovery: service: ${spring.application.name:DEFAULT-SERVICE-NAME} username: ${spring.cloud.nacos.username:nacos} password: ${spring.cloud.nacos.password:nacos} namespace: 2022-4-1-prod cluster-name: DEFAULT feign: httpclient: enabled: true
2、调用测试
①、SPRING-CLOUD-SERVICE-CONFIG-PROVIDER 服务
@RestController @RequestMapping("/config") @RefreshScope public class ConfigController { @Autowired private Student student; @GetMapping("/student") public String getStudent(HttpServletRequest request) { int port = request.getServerPort(); String servletPath = request.getServletPath(); String serverName = request.getServerName(); String api = serverName + ":" + port + servletPath; JSONObject jsonObject = new JSONObject(); jsonObject.put("API", api); jsonObject.put("student", student); return JSONObject.toJSONString(jsonObject); } }
接口 http://192.168.159.1:20002/config/student
②、SPRING-CLOUD-SERVICE-OPENFEIGN 服务
启动类开启注解
@SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class SpringCloudStarterOpenfeignExamplesApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudStarterOpenfeignExamplesApplication.class, args); } }
新建 ProviderClient 服务接口
@Service @FeignClient("SPRING-CLOUD-SERVICE-CONFIG-PROVIDER") public interface ProviderClient { @GetMapping("/config/student") String selectService(); }
调用 SPRING-CLOUD-SERVICE-CONFIG-PROVIDER 服务
@RestController @RequestMapping("/openfeign") public class OpenFeignController { @Autowired private ProviderClient providerClient; @GetMapping("/select") public String selectService() { return providerClient.selectService(); } }
访问接口:http://127.0.0.1:20004/openfeign/select
3、使用 OpenFeign 接口注解
OpenFeign 默认支持 springmvc 默认注解(@GetMapping、@PostMapping、@Param、@RequestMapping)
如果要使用 OpenFeign 自带的如下接口注解
需要配置 feign 的合约模式,如果不配置就是用如上注解会报错not annotated with HTTP method type (ex. GET, POST)
,注入如下 bean 即可@Configuration public class FeignConfiguration { //Contract feign的默认合约 @Bean public Contract feignContract() { return new Contract.Default(); } }
SpringMVC 注解和 OpenFeign 不能共存
4、OpenFeign 配置优先级
如果我们同时创建 @Configuration @bean 和 yaml 配置文件配置,配置文件将覆盖 @Configuration值。
你可以将 feign.client.default-to-properties 改成 false,则 @Configuration 覆盖配置文件5、OpenFeign GET 将 POJO 用作 GET 参数映射
①、服务提供者
控制层接口
@RestController @RequestMapping("/discovery") public class DiscoveryController { @GetMapping(value = "/pojo") public String selectPojo(HttpServletRequest request) { Map<String, String[]> parameterMap = request.getParameterMap(); JSONObject jsonObject = new JSONObject(); for (String s : parameterMap.keySet()) { if (parameterMap.get(s).length == 1) { jsonObject.put(s, parameterMap.get(s)[0]); } else { jsonObject.put(s, parameterMap.get(s)); } } return jsonObject.toJSONString(); } }
接口:http://127.0.0.1:20001/discovery/pojo?birthday=2022-02-22&username=admin&password=123456&address=西安
②、服务消费者
有的时候 GET 请求拼接 url 比较麻烦,则使用 @SpringQueryMap 注解将 POJO 对象用作 GET 参数映射
- OpenFeign @QueryMap 注解支持将 POJO 用作 GET 参数映射。不幸的是,默认的 OpenFeign QueryMap 注解与 Spring 不兼容,因为它缺少value属性。
- Spring Cloud OpenFeign 提供了等效的 @SpringQueryMap 注解,用于将 POJO 或 Map 参数注解为查询参数映射。
Feign 接口
@FeignClient(name = "SPRING-BOOT-SERVICE-DISCOVERY-CONSUMER") @Service public interface BootDiscoveryClient { @GetMapping(value = "/discovery/pojo") String selectPojo(@SpringQueryMap Map map); }
控制层接口
@RestController @RequestMapping("/openfeign") public class OpenFeignController { @Autowired private BootDiscoveryClient bootDiscoveryClient; @GetMapping(value = "/pojo") public String selectPojo(@RequestBody Map map) { return bootDiscoveryClient.selectPojo(map); } }
测试接口:http://127.0.0.1:20004/openfeign/pojo
@SpringQueryMap 注解将 pojo 参数拼接在 url 后面
http://SERVICE-NAME/discovery/pojo?birthday=2022-02-22&username=admin&password=123456&address=西安
之后根据负载均衡查找服务,将服务名替换成真实的地址去访问6、OpenFeign GET 请求带 body
关于 get 请求传递 body 详细说明 https://zhuanlan.zhihu.com/p/456921996,简单说 get 请求不建议传递 body ,某些浏览器可能不支持
- 支持 GET 请求 body: curl 、postman 、node.js 内置模块 http 、axios 、 Apache HttpClient 等
- 不支持 GET 请求 body: HttpUrlConnection 、OkHttpClient
OpenFeign 有 Apache HttpClient 、OkHttp 、HttpUrlConnection 三种实现方式
HttpClient 支持 Get 请求传递 body,OkHttp 和 HttpUrlConnection 不支持,下面讲解 HttpClient 实现方式
①、Apache HttpClient 支持 Get 请求传递 body
服务提供者
@RestController @RequestMapping("/discovery") public class DiscoveryController { @GetMapping(value = "/json", consumes = MediaType.APPLICATION_JSON_VALUE) public String selectStudent(@RequestBody Student student) { return JSONObject.toJSONString(student); } }
服务提供者接口:http://127.0.0.1:20001/discovery/json
服务消费者
控制层接口
@RestController @RequestMapping("/openfeign") public class OpenFeignController { @Autowired private BootDiscoveryClient bootDiscoveryClient; @GetMapping(value = "/json") public String selectStudent(@RequestBody Map map) { return bootDiscoveryClient.selectStudent(map); } }
feign 接口
@FeignClient(name = "SPRING-BOOT-SERVICE-DISCOVERY-CONSUMER") @Service public interface BootDiscoveryClient { @GetMapping(value = "/discovery/json") String selectStudent(@RequestBody Map map); }
服务消费者接口:http://127.0.0.1:20004/openfeign/json
②、OkHttpClient 不支持 Get 请求传递 body
查看 OkHttpClient 源码可以看到,如果 body 不为空,请求方式为 GET 或 HEAD 则抛出异常
public static boolean permitsRequestBody(String method) { return !method.equals("GET") && !method.equals("HEAD"); } public Request.Builder method(String method, @Nullable RequestBody body) { if (method == null) { throw new NullPointerException("method == null"); } else if (method.length() == 0) { throw new IllegalArgumentException("method.length() == 0"); } else if (body != null && !HttpMethod.permitsRequestBody(method)) { throw new IllegalArgumentException("method " + method + " must not have a request body."); } else if (body == null && HttpMethod.requiresRequestBody(method)) { throw new IllegalArgumentException("method " + method + " must have a request body."); } else { this.method = method; this.body = body; return this; } }
四、OpenFeign 负载均衡
1、OpenFeign 和 Feign 的区别
- Feign 是 Spring Cloud 组件中一个轻量级 RESTful 的 HTTP 服务客户端
- Feign 基于 ribbon 实现,可以理解为对 ribbon 的进一步封装
- Feign 不是做负载均衡的,feign 只是集成了 ribbon,负载均衡还是 feign 内置的 ribbon 做。
- Feign 的作用的替代 RestTemplate,性能比较低,但是可以使代码可读性很强。
- OpenFeign 在 Feign 的基础上支持了 SpringMVC 的注解
2、默认负载均衡
从 BaseLoadBalancer 类可以看到, OpenFeign 负载均衡默认 RoundRobinRule 轮询方式
protected IRule rule = DEFAULT_RULE; private final static IRule DEFAULT_RULE = new RoundRobinRule(); public Server chooseServer(Object key) { if (counter == null) { counter = createCounter(); } counter.increment(); if (rule == null) { return null; } else { try { return rule.choose(key); } catch (Exception e) { logger.warn("LoadBalancer [{}]: Error choosing server for key {}", name, key, e); return null; } } }
3、简单测试
将
SPRING-CLOUD-SERVICE-CONFIG-PROVIDER
服务打成 jar,启动三个服务(如果是集群模式,要将服务放在云服务器,默认使用 内网 IP,不使用公网 IP,可以在启动时指定公网IP nohup java -Dfile.encoding=utf-8 -jar nacos-springcloud-config-examples-0.0.1-SNAPSHOT.jar --server.port=10002 --spring.cloud.nacos.discovery.ip=99.99.99.99 >> cloud.txt &)下面的适用于局域网服务注册
java -Dfile.encoding=utf-8 -jar nacos-springcloud-config-examples-0.0.1-SNAPSHOT.jar --server.port=10002
java -Dfile.encoding=utf-8 -jar nacos-springcloud-config-examples-0.0.1-SNAPSHOT.jar --server.port=20002
java -Dfile.encoding=utf-8 -jar nacos-springcloud-config-examples-0.0.1-SNAPSHOT.jar --server.port=30002
启动之后查看 nacos 服务控制台,可以看到
SPRING-CLOUD-SERVICE-CONFIG-PROVIDER
服务有三个实例
接口访问:http://127.0.0.1:20004/openfeign/select如下可以看到默认负载均衡轮询
92.168.159.1:10001 92.168.159.1:10002 92.168.159.1:10003
4、解决错误
将项目打成 jar 包,读取 nacos 配置可能报错
org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException: Input length = 1
报错原因: nacos 读取配置文件默认使用 UTF-8,通过 cmd 启动项目,项目默认编码格式为 GBK解决方式 :添加启动参数-Dfile.encoding=utf-8
命令:java -Dfile.encoding=utf-8 -jar nacos-springcloud-config-examples-0.0.1-SNAPSHOT.jar --server.port=10002
五、自定义负载均衡
spring-cloud-ribbon 文档:https://docs.spring.io/spring-cloud-netflix/docs/2.2.9.RELEASE/reference/html/#spring-cloud-ribbon
1、IRule 负载均衡规则接口
IRule 负载均衡规则接口
负载均衡类说明负载均衡实现 策略 RandomRule 随机 RoundRobinRule 轮询 AvailabilityFilteringRule 先过滤掉由于多次访问故障的服务,以及并 发连接数超过阈值的服务,然后对剩下的服 务按照轮询策略进行访问; WeightedResponseTimeRule 根据平均响应时间计算所有服务的权重,响应时间越快服务权重就越大被选中的概率即越高,如果服务刚启动时统计信息不足,则 使用RoundRobinRule策略,待统计信息足够会切换到该 RetryRule 先按照RoundRobinRule策略分发如果分发 到的服务不能访问,则在指定时间内进行重试,然后分发其他可用的服务; BestAvailableRule 先过滤掉由于多次访问故障的服务,然后选 择一个并发量最小的服务; ZoneAvoidanceRule (默认) 综合判断服务节点所在区域的性能和服务节 点的可用性,来决定选择哪个服务; 2、Feign 代码配置负载均衡随机策略
①、@RibbonClient 不同服务配置不同的负载均衡
@RibbonClient 目的
- @RibbonClient如果不添加,则当前项目调用的所有服务都是用该负载均衡策略
- 如果当前项目有多个服务,可以指定每个服务的负载均衡策略
- 自定义负载均衡配置类不能放在启动类包及其子包下,否则所有的服务共用一个策略,@RibbonClient 中的 name 将不起作用
- @RibbonClient 注解可以把其他的配置类作为另外一个IOC容器导入到应用中,相当于加载了两个完全不相干的Spring的beans配置文件,此时应用中会有两个IOC容器。
项目结构,添加的两个负载均衡不在启动类同包以及扫描包下
负载均衡随机策略 MyRandomRule,自定义负载均衡算法 MyDiyRule 下面步骤 3@Configuration public class MyRandomRule { @Bean public IRule ribbonRule() { return new RandomRule(); // 采用随机策略 } }
@RibbonClient 不同服务配置不同策略,下面两个类随便添加进启动类或者子包下的类即可
@Configuration @RibbonClient(name = "SPRING-BOOT-SERVICE-DISCOVERY-CONSUMER", configuration = MyDiyRule.class) class MyDiyRuleConfigRibbonClient { } @Configuration @RibbonClient(name = "SPRING-CLOUD-SERVICE-CONFIG-PROVIDER", configuration = MyRandomRule.class) class ConfigRibbonClient { }
②、配置文件服务配置不同的负载均衡
bootstrap.yaml 添加负载均衡配置(MyDiyRule、MyRandomRule 和上面同一个类)SPRING-BOOT-SERVICE-DISCOVERY-CONSUMER: ribbon: NFLoadBalancerRuleClassName: com.ribbon.MyDiyRule SPRING-CLOUD-SERVICE-CONFIG-PROVIDER: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 上面的是 netflix 自带的随机算法,或者使用下面的是自定义的随机策略 # NFLoadBalancerRuleClassName: com.ribbon.MyRandomRule
③、测试
SPRING-CLOUD-SERVICE-CONFIG-PROVIDER 服务随机策略:http://127.0.0.1:20004/openfeign/select
SPRING-BOOT-SERVICE-DISCOVERY-CONSUMER 自定义负载均衡策略:http://127.0.0.1:20004/openfeign/rule
3、自定义算法实现负载均衡
仿照 IRule 的接口实现类轮询策略 RoundRobinRule,实现自定义算法负载均衡,保证每个服务访问 3 次,切换其他服务
public class MyRule extends AbstractLoadBalancerRule { private int total; private int currentIndex; public Server choose(ILoadBalancer lb, Object key) { if (lb == null) { return null; } Server server = null; while (server == null) { if (Thread.interrupted()) { return null; } // 获取运行中的服务 List<Server> upList = lb.getReachableServers(); // 获取所有服务 List<Server> allList = lb.getAllServers(); int serverCount = allList.size(); if (serverCount == 0) { return null; } // 简单的判断,保证每个服务执行 5 次 if (total % 3 == 0) { if (currentIndex < upList.size()-1) { currentIndex++; } else { currentIndex = 0; this.total = 0; } } total++; // 从活着的服务中获取 server = upList.get(currentIndex); if (server == null) { Thread.yield(); continue; } if (server.isAlive()) { return (server); } server = null; Thread.yield(); } return server; } @Override public Server choose(Object key) { return choose(getLoadBalancer(), key); } @Override public void initWithNiwsConfig(IClientConfig clientConfig) {} }
测试自定义负载均衡策略
六、熔断降级控制组件
OpenFeign 默认引入了 Hystrix 服务控制组件
Hystrix 和 Sentinel 都是分布式服务架构中服务熔断降级控制组件,Sentinel 和 Hystrix 对比选型可参考
Hystrix 概念简单实用参考:https://blog.csdn.net/qq_38149225/article/details/109454418
Sentinel 使用参考:https://github.com/alibaba/Sentinel/wiki/如何使用1、服务雪崩
分布式系统环境下,服务间类似依赖非常常见,一个业务调用通常依赖多个基础服务。
如果由于流量激增,线程数有限,会导致访问超时,最终导致 C 服务失请求败,则 B 服务也会失败,最终导致 A 服务失败。简单说:一个服务失败,导致整条链路的服务都失败的,我们称之为服务雪崩。
2、引起雪崩的原因和服务雪崩的三个阶段
原因大致有四:
- 1、硬件故障;
- 2、程序Bug;
- 3、缓存击穿(用户大量访问缓存中没有的键值,导致大量请求查询数据库,使数据库压力过大);
- 4、用户大量请求;
服务雪崩三个阶段:
- 第一阶段: 服务不可用;
- 第二阶段:调用端重试加大流量(用户重试/代码逻辑重试);
- 第三阶段:服务调用者不可用(同步等待造成的资源耗尽);
3、雪崩解决方法
服务熔断:在一定时间内一定请求某个服务响应超时,则停止访问
服务降级:当某个服务熔断之后,服务将不再被调用,此时客户端可以自己准备一个本地的fallback(回退)回调,返回响应一个缺省值。 例如:(备用接口/缓存/MySQL/mock数据) 。这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强,当然这也要看适合的业务场景。七、hystrix 服务降级简单测试
openfeign hystrix 参考:https://docs.spring.io/spring-cloud-openfeign/docs/2.2.9.RELEASE/reference/html/#creating-feign-clients-manually
netflix hystrix 参考:https://docs.spring.io/spring-cloud-netflix/docs/2.2.9.RELEASE/reference/html/#circuit-breaker-hystrix-clients1、服务消费者
pom.xml 核心依赖如下,openfeign 包含 hystrix
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
bootstrap.yaml 启用 hystrix 断路器,Feign 将使用断路器包装所有方法
- Feign 开启 hystrix 断路器
feign.hystrix.enabled=true
- Feign 关闭 spring cloud 断路器
feign.circuitbreaker.enabled=true
feign: hystrix: enabled: true circuitbreaker: enabled: false
注意:启动类不能添加 @EnableCircuitBreaker ,如果添加该注解需要导入 spring-cloud-starter-netflix-hystrix 依赖
@SpringBootApplication @EnableDiscoveryClient @EnableFeignClients //@EnableCircuitBreaker public class SpringCloudStarterOpenfeignExamplesApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudStarterOpenfeignExamplesApplication.class, args); } }
BootDiscoveryClient.java
@FeignClient(name = "SPRING-BOOT-SERVICE-DISCOVERY-CONSUMER",fallback = BootFallbackService.class) @Service public interface BootDiscoveryClient { @GetMapping(value = "/hystrix/calculate") String serviceDown(@SpringQueryMap Map map); }
BootFallbackService.java 当请求超时错误回退类,需要声明为 spring bean,注意不能使用 @Controller 相关注解
@Component public class BootFallbackService implements BootDiscoveryClient { @Override public String serviceDown(Map map) { return "serviceDown 方法请求获取数据超时或错误,进行了服务降级操作"; } }
服务消费者接口
@RestController @RequestMapping("/hystrix") public class HystrixController { @Autowired private BootDiscoveryClient bootDiscoveryClient; @GetMapping(value = "/calculate") public String serviceDown(String a,String b,String type) { Map<String,String> map = new HashMap<>(); map.put("a",a); map.put("b",b); map.put("type",type); return bootDiscoveryClient.serviceDown(map); } }
⭐⭐⭐⭐⭐⭐ 访问回退原因 ⭐⭐⭐⭐⭐⭐
FeignClient 接口
@Service @FeignClient(value = "SPRING-CLOUD-SERVICE-CONFIG-PROVIDER",fallbackFactory = HystrixClientFallbackFactory.class) public interface CloudConfigClient { @GetMapping("/config/student") String selectService(); }
HystrixClientFallbackFactory 回退类
@Component public class HystrixClientFallbackFactory implements FallbackFactory<CloudConfigClient> { @Override public CloudConfigClient create(Throwable throwable) { return new CloudConfigClient() { @Override public String selectService() { JSONObject jsonObject = new JSONObject(); jsonObject.put("message", "selectPojo 方法请求获取数据超时或错误,进行了服务降级操作"); jsonObject.put("code", 444); jsonObject.put("err", throwable.getMessage()); return jsonObject.toJSONString(); } }; } }
测试 :http://127.0.0.1:20004/openfeign/select
服务提供者 debug,会导致读取超时,测试服务降级获取接口访问失败回退原因
2、服务提供者
服务提供者接口, @ApiAnnotation 为自定义注解,目的返回结果封装 url
@GetMapping("/calculate") @ApiAnnotation public String calculate(String a, String b, String type) { int result = 0; int num1 = Integer.parseInt(a); int num2 = Integer.parseInt(b); switch (type) { case "+": result = num1 + num2; break; case "-": result = num1 - num2; break; case "*": result = num1 * num2; break; case "/": result = num1 / num2; break; } return String.valueOf(result); }
3、测试
测试可以在服务提供者打断点模拟读取超时或者 10/0 抛一个算术异常
接口:http://127.0.0.1:20004/hystrix/calculate?a=10&b=0&type=/
4、Hystrix 断路器监控
Spring Cloud 断路器监控(Hystrix Dashboard)
八、Sentinel 简单测试
参考我的另一篇博客:https://blog.csdn.net/qq_41538097/article/details/124330640
-
10.OpenFeign之第一个Feign程序(更新)
2018-05-17 13:31:23Feign是一个Java到HTTP客户端绑定器,它的灵感来自于Retrofit,JAXRS-2.0和WebSocket。Feign的主要目的是将绑定命名的复杂性降低到HTTP api不去考虑rest的复杂性。 -
spring-boot-openfeign-restcountries-example:OpenFeign和Thymeleaf的Spring Boot示例以及RestCountries ...
2021-03-27 13:00:08spring-boot-openfeign-restcountries-example:OpenFeign和Thymeleaf的Spring Boot示例以及RestCountries REST服务中的数据 -
feign和openFeign区别和openFeign教程
2022-02-17 23:46:59一、Feign与OpenFeign的区别 1)Feign是Spring Cloud组件中一个轻量级RESTful的HTTP服务客户端,Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。Feign的使用方式是:使用Feign的注解定义接口... -
openfeign+hystrix
2022-04-08 17:15:32openfeign+hystrix+eureka+ribbon 服务降级、负载均衡、客户端远程调用、注册中心