SpringCloud Feign实现微服务间的远程调用(黑马头条Day04)
Feign是一个声明式的Web Service客户端。它让微服务之间的调用变得更简单。Feign具有可插拔式的注解支持,包括Feign 注解和JAX-RS注解。Feign还支持可插拔的编码器和解码器。Spring Cloud增加了对Spring MVC注解的支持,并且也支持Spring WebFlux。
目录
在wemedia微服务中添加@EnableFeignClients注解,并指定需要扫描的包
在wemedia微服务中注入article微服务中Feign接口的实现类,调用对应实现方法
Feign介绍
Feign是一个声明式的Web Service客户端。它让微服务之间的调用变得更简单。Feign具有可插拔式的注解支持,包括Feign 注解和JAX-RS注解。Feign还支持可插拔的编码器和解码器。Spring Cloud增加了对Spring MVC注解的支持,并且也支持Spring WebFlux。
在开发中,我们常用httpClient去远程调用其他系统的接口,需要我们指定调用的url(参考苍穹外卖中的调用支付等第三方接口),Feign 是一个声明式的 Web Service 客户端,它实现了一套远程调用的方法,调用的方式也更为优雅。
前提:1.被调用的模块注册到eureka\nacos中,能正常运行
2.feign接口文件夹要和启动类在同一个目录下, 否则需指定包名,@EnableFeignClients(basePackages="com.**.***")
常见API调用方式有哪些
在日常工作中,我们经常会遇到需要调用内部 API 或者第三方 API 的情况,主要有以下方式:
- HttpURLConnection
- HttpClient
- OKHttp
- RestTemplate
以上这四种是我们最常见的 API 调用方式,在调用 API 之前,我们首先需要知道 API 的地址,其次是 API 对应的参数,然后发起调用,本质上调用 API 的过程就是一个 HTTP 请求过程。
如果你用过 Dubbo 框架,就会知道在 Dubbo 中发起远程调用是不需要使用者去关注服务提供者信息的,直接注入一个接口,然后调用接口中的方法,就像调用本地方法一样。这样的好处是开发效率高,代码优雅。(Dubbo和Feign的区别)
Feign相较于RestTemplate的优势
- 使用带注解的接口来定义服务客户端。
- 与 Spring Cloud 无缝集成,利用服务发现。
- 在运行时自动实现接口。
- 提供更高级别的抽象,减少对重复样板代码的需求。
Feign的执行流程
Feign在调用其他服务时,会根据注解中的url进行请求转发。它的工作原理是:
- 根据
@FeignClient
的value值找到服务,如果配置了服务注册中心,还会根据服务名获取服务实例列表。- 构造请求参数,根据方法上的注解(如@PathVariable、@RequestParam、@RequestBody等)确定请求参数。
- 根据注解(@GetMapping、@PostMapping、@DeleteMapping等)确定请求方法和路径。
- 发起请求调用其他服务,获取结果。
- 封装结果,返回给调用方。
项目中使用Feign介绍
黑马头条作为一个典型的微服务项目,涉及到多个微服务,如上图中③媒体微服务,可以对用户发布的文章进行审核;②文章微服务,在用户发布的文章经过媒体微服务审核后,利用文章微服务将其存储到文章相关表格中。②和③对应的微服务之间并没有建立直接的联系,此时使用feign远程调用,在③中方便调用②中提供的服务。结构如下:
大致思路如下:
- 在feign-api(①)微服务中定义feign的接口,并通过@FeignClient(...)注解指定要调用的服务名称。
- 在article(②)微服务中创建feign接口的实现类,并实现具体业务逻辑,向文章相关表格中插入对应数据。
- 在wemedia(③)微服务中注入②中创建的接口的实现类,直接调用②中实现的方法。(面向接口编程)。
实现步骤
添加Feign依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
注册feign远程调用接口,并指定需要调用的微服务
@FeignClient(value = "leadnews-article")
public interface IArticleClient {
@PostMapping("/api/v1/article/save")
public ResponseResult saveArticle(@RequestBody ArticleDto dto);
}
通过@FeignClient(...)注解指定要调用的微服务【leadnews-article(②)】,通过@PostMapping(...)注解指定其访问路径。
在leadnews-artilce微服务中创建接口实现类
@RestController
@Slf4j
public class ArticleClient implements IArticleClient {
@Autowired
private ApArticleService apArticleService;
/**
* 修改或保存文章信息
* @param dto
* @return
*/
@PostMapping("/api/v1/article/save")
@Override
public ResponseResult saveArticle(@RequestBody ArticleDto dto) {
log.info("修改或保存文章信息:{}", dto);
return apArticleService.saveArticle(dto);
}
}
在wemedia微服务中添加@EnableFeignClients注解,并指定需要扫描的包
上图中指定扫描的包为basePackages = "com.heima.apis",由于Feign接口所在的包的微服务并不是调用者所在的微服务并不会扫描对应的包,需要指定。
在wemedia微服务中注入article微服务中Feign接口的实现类,调用对应实现方法
@Autowired
private IArticleClient iArticleClient;
@Autowired
/**
* 审核成功,保存app端的相关文章数据
* @param wmNews
*/
private ResponseResult saveAppArticle(WmNews wmNews) {
// ......
ResponseResult responseResult = iArticleClient.saveArticle(dto);
return responseResult;
}
Figen和SpringCloud集成的高级特性
无缝的服务发现和调用
从本质上讲,Feign 和服务发现的结合使一个服务能够轻松发现另一个服务并与另一个服务进行通信,而无需硬编码 URL 或管理负载均衡器:
- 服务注册:使用@EnableDiscoveryClient,您的服务可以将自身注册到服务注册表(例如Eureka或Consul或Nacos)。这提供了所有可用服务及其实例的动态目录。
- 服务调用:使用@EnableFeignClients,您可以声明服务的客户端接口。当你想与另一个服务通信时,你只需调用这个接口上的方法,Feign 就会处理剩下的事情。
这意味着如果serviceA想要与serviceB对话,它不需要知道serviceB位于哪里。它询问服务注册表,获取地址,然后 Feign 进行调用。这种无缝的相互作用消除了通常与服务间通信相关的大部分样板文件和操作开销
使用 Ribbon 进行负载均衡
Spring Cloud默认配置Feign使用Ribbon进行客户端负载均衡。与服务发现结合使用时: Feign 查询服务注册表以查找所需服务的所有实例。 ribbon负载平衡这些实例之间的请求。
此设置可确保即使一个服务实例关闭,您的请求也不会失败 - 它会被路由到另一个运行状况良好的实例。这提供了弹性和有效的流量分配。
具有动态接口的声明式 REST 客户端
考虑以下场景:您的微服务生态系统不断发展,服务可能在服务器之间移动、向上或向下扩展,甚至存在于多个版本中。跟踪接口可能是一场噩梦。
但是,当您将 @EnableFeignClients 与 @EnableDiscoveryClient 结合使用时,您会得到: 声明式 REST 客户端:使用 Feign 的注解定义一次客户端。不再需要管理 HttpClient 实例或手动解析响应。 动态接口:由于实际的服务位置是从服务注册表中检索的,因此即使服务已移动或扩展,您也始终会指向正确的地址。
使用 Hystrix 增强容错能力
Spring Cloud 允许 Feign 与容错库 Hystrix 集成。当服务无法响应(可能已关闭或过载)时,Hystrix 可以提供回退机制,确保您的应用程序保持响应。利用 Ribbon 的负载平衡功能和服务发现的动态端点解析来提供真正有弹性的系统
远程调用服务降级(Hystrix 增强容错能力)
Spring Cloud 允许 Feign 与容错库 Hystrix 集成。当服务无法响应(可能已关闭或过载)时,Hystrix 可以提供回退机制,确保您的应用程序保持响应。
服务降级:当服务调用失败或超时,我们需要有降级策略,避免影响整体系统。我们可以为Feign接口增加fallback
指定降级实现类。
Feign远程过程调用是一个独立的服务,可以和SpringCloud集成使用也可以单独使用,不要立即为Feign就是SpringCloud的一部分。
服务降级是服务自我保护的一种方式,或者保护下游服务的一种方式,用于确保服务不会受请求突增影响变得不可用,确保服务不会崩溃
服务降级虽然会导致请求失败,但是不会导致阻塞。
实现步骤
编写服务降级策略
/**
* feign失败配置
*/
@Component
public class IArticleClientFallback implements IArticleClient {
@Override
public ResponseResult saveArticle(ArticleDto dto) {
return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"保存数据失败");
}
}
接口实现类所在的微服务中扫描服务降级所在的包,并通过@FeignClient(...)注解中的fallback属性指定服务降级的类。
@Configuration
@ComponentScan("com.heima.apis.article.fallback")
public class InitConfig {
}
@FeignClient(value = "leadnews-article",fallback = IArticleClientFallback.class)
public interface IArticleClient {
@PostMapping("/api/v1/article/save")
public ResponseResult saveArticle(@RequestBody ArticleDto dto);
}
在调用者所在的微服务wemedia中添加具体超时设置
feign:
# 开启feign对hystrix熔断降级的支持
hystrix:
enabled: true
# 修改调用超时时间
client:
config:
default:
connectTimeout: 2000
readTimeout: 2000
其中connectTimeout指定连接超时,默认10s;readTimeout指定读取超时,默认60s。
参考链接
Feign实现远程接口的调用_feign远程调用接口的实现-CSDN博客
五、声明式服务调用-Feign - 知乎 (zhihu.com)
微服务服务间调用组件Feign使用介绍、原理、优化技巧-腾讯云开发者社区-腾讯云 (tencent.com)
SpringCloud中的@EnableDiscoveryClient 和 @EnableFeignClients - 知乎 (zhihu.com)
更多推荐
所有评论(0)