3.3 【实例】Feign调用微服务接口
3.3.1 实例背景
目前已有cloud-user-8083工程和cloud-common-jar工程,本实例将创建cloud-admin-8084工程,此工程同样引入common-jar工程,然后用cloud-admin-8084工程调用cloud-user-8083工程中的相关接口。
cloud-admin-8084工程的application资源配置文件与cloud-user-8083工程中的资源配置文件基本相同,可参考2.3.5节,注意修改spring.application.name微服务名称即可。如果spring.application.name微服务名称相同导致重名,就会找不到相关服务,从而无法正常运行。
3.3.2 引入相关配置信息
虽然依赖spring-cloud-starter-feign和feign-core的结果基本相同,但依旧推荐依赖spring-cloud-starter-feign,因为此处含有许多netflix其他相关依赖内容与组件,能够减轻依赖上的负担,并且防止出现的一些未知异常。
pom.xml文件部分新增代码如下。
spring-cloud-starter-feign的内部依赖代码如下。
3.3.3 编写Feign客户端
通过@FeignClient注解,Feign定义该IndexService对应Consul中注册的某个微服务,Value参数输入微服务的名称,即提供服务工程的spring.application.name,并在IndexService.java中编写cloud-user微服务的相关接口,然后在其他Service中直接注入IndexService,即可获得cloud-user微服务的相关服务。
编写Feign客户端对应cloud-user微服务的IndexService代码如下。
@FeignClient注解配置的参数及释义如表3-6所示。
表3-6 @FeignClient注解配置的参数及释义
如果使用@GET/@POST等第三方JAXRS注解,需要告知@FeignClient正在使用第三方JAXRS注解,并指定第三方注解翻译器才可使用JAXRS注解。指定翻译器需在Contract中编写new JAXRSContract()。
@RequestMapping注解是Feign用来对应定义的HTTP接口地址,在REST风格下使用@GET、@POST等相关注解也可。
Feign提供了@RequestLine注解用于对应HTTP接口,其作用等效于@RequestMapping,写法如下。
@Headers注解是Feign用来增加报文头内部信息的注解。输入String[]数组可用来输入多个HTTP报文头的信息,此处采用json编码格式。
@RequestLine注解常用写法如下。
注意,在上述代码中GET/POST与后面的映射路径间有一个空格。
3.3.4 编写调用
编写cloud-admin-8084工程的IndexController.java文件代码如下,用于cloud-admin-8084工程调用cloud-user-8083工程的相关服务。
因为Feign对调用的接口进行了实例化,所以调用服务的相关代码,可直接将indexService通过Spring容器注入Controller中使用。若用实现的方式写上述代码,伪代码如下。
注意,以上伪代码尽量不要在微服务分布式群中微服务互相调用时使用,否则日后维护会十分困难。
3.3.5 编写启动类
Feign的客户端需要使用@EnableFeignClient注解来启动Feign客户端的相关注解能力。ApplicationMain8084.java启动类文件的代码如下。
3.3.6 当前项目结构
图3-16中的cloud-admin-8084工程,通过Feign Client请求图3-17中cloud-user-8083工程的@RestController接口。
图3-16
图3-17
图3-16中的cloud-admin-8084工程与图3-17中的cloud-user-8083工程都依赖图3-18中的cloud-common-jar工程。
图3-18
3.3.7 运行结果
运行cloud-admin-8084工程和cloud-user-8083工程后,使用cloud-admin-8084的接口,可以看到index接口已经调用了cloud-user-8083的getUser接口。由此实现了通过一个注解让两个微服务进行通信,运行结果如图3-19所示。
图3-19
后台日志输出片段如下。
netflix在调用之前,依靠BaseLoadBalancer负载均衡器实例化了Feign服务的客户端。BaseLoadBalancer相当于“服务池”,其内部维护了一个相对完整的服务列表。若用户需要调用注册中心的任何服务,则需要通过BaseLoadBalancer实例化服务。BaseLoadBalancer服务池中也可以设置Ping心跳,以确定“服务列表”中的服务是否正常使用。
3.3.8 实例易错点
1.没有找到响应的微服务
如果在编写@FeignClient(value="cloud-user")注解时,value内部对应的微服务名称填写有误,在微服务启动的过程中不会报错,但是在调用Feign服务时,会报如下错误。
上述错误表示没有找到cloud-user微服务,此时只要检查哪里写了cloud-user即可。若确定微服务名称正确,则检查cloud-user微服务是否已经启动。
2.不要用下画线作为微服务的名称
在3.3节的工程中使用减号“-”构建微服务的名称,如cloud-user。如果使用下画线“_”构建微服务名称,在服务端微服务运行、启动及注册到Consul注册中心上都不会出现问题,一旦Feign的调用方调用含有“_”的工程时,可能因为字符转义或其他因素,在调用方启动项目时出现如下错误。
3.Swagger与Feign版本冲突
低版本Swagger与Feign可能冲突,导致出现Spring容器无法正常实例化Service等相关错误,此时升级Swagger到2.7以上版本即可,其错误如下。