SpringCloud-Netflix(Usage of OpenFeign)
SpringCloud-Netflix(Usage of OpenFeign)
前面我们使用的Ribbon+Resttemplate进行微服务之间的调用,然而,这种方式还是要我们手动填写目标的服务地址。一个好的架构的话,开发人员应该对服务调用无感知,这样才能减少错误的频率,那么openfeign就可以帮我们做到这点。我们服务调用之间可以就像调用本地接口一样进行调用。它的底层会帮我们生成http的url地址,本篇会聊到:
- openfeign的使用
- openfeign的相关设计
The usage of openfeign
【整体想法】:
想要像调用本地服务一样的,调用远程服务的话,我们肯定要有一个公共的接口作为载体,让服务调用者和服务提供者都可以使用。如果这样的话,我们其实就可以为每一个服务提供者新建一个api的项目,然后我们的服务提供者引入api项目的依赖,同时,我们的服务调用者也引入这个api的依赖。然后feign通过解析就可以把他们连接到一起。
【现有条件】:
现在有一个商品的微服务,并且有一个公共的对外暴露的服务(用于接受前端请求),现在我们要在这个对外暴露的项目中像调用本地服务一样调用商品的微服务
【具体步骤】:
创建商品服务的api的pom工程,并且创建一个接口,供给商品服务的微服务项目实现,当有业务代码需要写的时候在这个接口中填充内容。
View Codepublic interface IGoodsService { @GetMapping("/goods") String getGoodsById(); }在api工程中引入openfeign,并且新建另外一个接口,这个接口需要标注openfeign的注解,注解中的名称就填写相关的服务提供者的名称(application中的),并且实现业务的接口(这里使用两个接口的原因是,一个是为业务提供的,一个是为了openfeign解析微服务路径的)
View Code@FeignClient(name = "goods-service") public interface IGoodsServiceFeignClient extends IGoodsService { }在api工程中引入openfeign的starter
View Code<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>在服务提供者的工程中引入api的pom依赖,这样就可以共用一个接口。并且在服务提供者中的controller中实现这个接口
View Code<dependency> <groupId>com.glenmall.mall</groupId> <artifactId>goods-service-api</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>View Code@RestController @Slf4j public class GoodsService implements IGoodsService { @Value("${server.port}") private String port; /** * 根据ID查询商品信息 * @return */ @GetMapping("/goods") public String getGoodsById(){ log.info("收到请求,端口为:{}",port); return "返回商品信息"; } }在我们的公共api模块中引入openfeign的starter
View Code<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>并且在公共的api模块中引入商品服务的api,这样在公共api模块中就可以使用商品模块的接口进行调用
View Code<dependency> <groupId>com.glenmall.mall</groupId> <artifactId>goods-service-api</artifactId> </dependency>这个时候就可以在公共的api中调用商品模块的接口。
View Code@Autowired IGoodsService iGoodsService; String goodsById = iGoodsService.getGoodsById();
同时我们还需要在公共api的接口项目中的启动类上加上【@EnableFeignClients(basePackages = "标注了feign接口的报名")->会对它进行扫描】
整体流程梳理:
当一个请求到了我们的公共服务,因为公共服务中我们引入了商品模块的api,所以可以对这个接口进行注入从而调用。在api中有两个接口,一个接口是对于商品服务的提供者进行实现的,另外一个接口实现了这个接口,并且标注了openfeign的注解,用于openfeign进行地址解析的。
relevant characteristic
openfeign整个调用链路:
- 当我们统一api的服务注入商品服务的时候,实际上他注入的是一个动态代理的实例(openfeign去扫描@EnableFeignClient路径中标记@FeignClient的类并且生成动态代理)。
- 当发起http请求后(openfeign会解析我们标注FeignClient的注解并且解析成http地址,并且转发到目标请求,因为标注@feignclient接口上有微服务的名称,接口方法中有微服务的地址),会转发到目标微服务
- 注:引入了openfeign后,在openfeign解析http地址的时候,底层还是依靠Ribbon去获取的一些地址。