1 本文目标
通过本章节,将掌握Feign接口的开发及使用,Feign常用的安全机制。
1.1 Feign简单介绍
微服务之前的通信、服务调用,可以通过Feign来实现,而其通讯的本质就是发送HTTP请求。
2 练习场景
本次练习需要创建三个模块:
- 客户管理微服务模块(custmng):服务提供方,提供客户额度管理查询功能;
- 信誉度管理微服务模块(creditmng):服务消费方,消费额度管理功能的查询功能;
- 客户管理Client模块(custmng-client):客户管理提供给其他微服务模块使用的接口模块;
前提:
3 操作步骤
为custmng微服务创建SDK模块
3.1 服务提供方custmng微服务
3.1.1 custmng-client模块创建
通常,某个微服务需要提供接口给其他微服务模块时,需要开发并封装Client模块,
其他微服务通过pom引入的方式,进行接口消费,且必须在统一注册中心集群环境下;
基于已经创建微服务工程->右键“模块”->选择Client
![](http://192.168.251.162:8090/download/attachments/5014729/image2019-3-13%2020%3A50%3A37.png?version=1&modificationDate=1552481363000&api=v2)
![](http://192.168.251.162:8090/download/attachments/5014729/image2019-3-14%2019%3A52%3A35.png?version=1&modificationDate=1552564279000&api=v2)
创建后工程结构
3.1.2 接口创建
在custmng-client工程下,应用开发->业务开发->业务逻辑->右键,新建类
DTO创建
package cn.com.yusys.yusp.service; import java.io.Serializable; /** * 额度实体表. * * @since 2.1.1 */ public class LimitInfoDTO implements Serializable{ private static final long serialVersionUID = 1L; /** * 额度ID */ private String limitId; /** * 额度代码 */ private String limitCode; /** * 额度金额 */ private String limitAmt; /** * 描述 */ private String limitDesc; /** * 客户ID */ private String limitUserId; /** * @param limitId */ public void setLimitId(String limitId) { this .limitId = limitId == null ? null : limitId.trim(); } /** * @return LimitId */ public String getLimitId() { return this .limitId; } /** * @param limitCode */ public void setLimitCode(String limitCode) { this .limitCode = limitCode == null ? null : limitCode.trim(); } /** * @return LimitCode */ public String getLimitCode() { return this .limitCode; } /** * @param limitAmt */ public void setLimitAmt(String limitAmt) { this .limitAmt = limitAmt == null ? null : limitAmt.trim(); } /** * @return LimitAmt */ public String getLimitAmt() { return this .limitAmt; } /** * @param limitDesc */ public void setLimitDesc(String limitDesc) { this .limitDesc = limitDesc == null ? null : limitDesc.trim(); } /** * @return LimitDesc */ public String getLimitDesc() { return this .limitDesc; } /** * @param limitUserId */ public void setLimitUserId(String limitUserId) { this .limitUserId = limitUserId == null ? null : limitUserId.trim(); } /** * @return LimitUserId */ public String getLimitUserId() { return this .limitUserId; } } |
3.1.3 创建Feign接口服务
package cn.com.yusys.yusp.service; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; /** * 额度管理API接口. * * @since 2.1.1 */ @FeignClient (name = "custmng" , path = "/api" , fallback = LimitInfoServiceHystrix. class ) public interface LimitInfoService { /** * 额度信息查询接口. * * @param limitId * 额度ID * @return */ @GetMapping (value = "/limitinfo/query" ) public LimitInfoDTO query( @RequestParam (value = "limitId" ) String limitId); } |
@FeignClient 标注此接口为Feign接口,需要通过@EnableFeignClients扫描后才会生效
name = custmng #微服务名称
value = /api/limitinfo/query #提供对外资源服务的API
method = RequestMethod.GET #HTTP方法类型
@RequestParam("limitId") String limitId#基于GET请求的参数传值
3.1.4 fallback开发
在一个分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,如何能够保证在一个依赖出问题的情况下,不会导致整体服务失败,这个就是Hystrix需要做的事情。Hystrix提供了熔断、隔离、Fallback、cache、监控等功能,能够在一个、或多个依赖同时出现问题时保证系统依然可。
要为给定的@FeignClient
启用回退,请将fallback
属性设置为实现Hystrix的类名.@FeignClient(fallback = LimitInfoServiceHystrix.class)
package cn.com.yusys.yusp.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; /** * 额度管理熔断处理实现类. * * @since 2.1.1 */ @Component public class LimitInfoServiceHystrix implements LimitInfoService { private static final Logger logger = LoggerFactory.getLogger(LimitInfoServiceHystrix. class ); @Override public LimitInfoDTO query(String limitId) { logger.warn( "访问失败,触发熔断" ); return null ; } } |
注意,此处只能使用@Component 注解
3.1.5 接口发布
完成接口自测后,即可将client包按照版本规范,发布到maven仓库,同时通过wiki或文档等方式,提供API、参数的说明文档。
在工程目录执行
mvn deploy -e -DskipTests |
发布前提
- 本机已安装apache maven
-
setting 配置maven私服账号信息
![](https://i-blog.csdnimg.cn/blog_migrate/0707c0b7a86d245ab8ed1edd872ec0c9.jpeg)
- 工程pom增加发布的具体仓库信息
![](https://i-blog.csdnimg.cn/blog_migrate/87cd234451a70254fd0efae537f8998d.jpeg)
3.2 消费者消费
3.2.1 创建creditmng微服务模块
该微服务工程开发为消费端,调用custmng提供第SDK接口;创建流程和custmng创建流程一直,此处不再重复讲解;
![](http://192.168.251.162:8090/download/attachments/5014729/image2019-3-14%2020%3A6%3A11.png?version=1&modificationDate=1552565095000&api=v2)
除了调整数据库、Redis配置,此微服务使用6002端口;
![](http://192.168.251.162:8090/download/attachments/5014729/image2019-3-14%2020%3A7%3A57.png?version=1&modificationDate=1552565201000&api=v2)
3.2.2 为/creditmng/pom.xml增加SDK包依赖
< dependency > < groupId >cn.com.yusys.yusp</ groupId > < artifactId >custmng-client</ artifactId > < version >2.1.1-SNAPSHOT</ version > </ dependency > |
3.2.3 增加@EnableFeignClients配置
CreditmngMicroserviceApp.java 增加@EnableFeignClients配置
消费方在消费服务提供发布的client包时,需要通过注解EnableFeignClients的方式开启Feign功能,同时,在注解中添加Feign接口需要扫描的包路径,
在应用入口的启动类上,添加了EnableFeignClients,如:@EnableFeignClients("cn.com.yusys.yusp")
@EnableConfigurationProperties ({ApplicationProperties. class }) @EnableDiscoveryClient @SpringBootApplication (scanBasePackages = { "cn.com.yusys.yusp" }, exclude = {JmxAutoConfiguration. class , ThymeleafAutoConfiguration. class , SecurityAutoConfiguration. class , JasyptSpringBootAutoConfiguration. class }) @MapperScan ({ "cn.com.yusys.yusp.repository.mapper" }) @EnableFeignClients ( "cn.com.yusys.yusp" ) @EnableTransactionManagement public class CreditmngMicroserviceApp { private static final Logger logger = LoggerFactory.getLogger(CreditmngMicroserviceApp. class ); public static void main(String[] args) { Environment env = SpringApplication.run(CreditmngMicroserviceApp. class , args).getEnvironment(); logger.info(AppStartMessageUtil.updServiceStartMessage(env)); } } |
或者是增加FeignConfiguration配置类,用于开启Feign配置,并为它设置相关的属性;
3.2.4 增加接口消费
在使用feign时,和常用bean注入方式一样,通过@Autowired注解,即可实现bean注入:
@RestController @RequestMapping ( "/api/consumer" ) public class ConsumberResource { @Autowired LimitInfoService limitInfoService; @GetMapping (value= "/query" ) public String query( @RequestParam (value= "limitId" ) String limitId) { LimitInfoDTO limitInfoDTO = limitInfoService.query(limitId); return Optional.ofNullable(limitInfoDTO) .map(LimitInfoDTO::getLimitDesc) .orElseGet(()-> "" ); } } |
3.3 测试
通过swagger进行测试,如果没有开启swagger,可以通过application.swagger.enabled=true开启
custmng、creditmng应用启动,可通过http://localhost:6002/actuator/beans 查看FeignBean注入信息
"cn.com.yusys.yusp.service.LimitInfoService" : { "aliases" : [ "custmngFeignClient" ], "scope" : "singleton", "type" : "cn.com.yusys.yusp.service.LimitInfoService", "resource" : null, "dependencies" : [ ] }, |
从以上内容可以了解到,每一个接口都会有一个别名:微服务+FeignClient,标识由bean是有feign创建。
3.3.1 调用custmng接口,查看服务提供方接口查询
http://172.16.20.208:6001/api/limitinfo/query?limitId=00000
![](http://192.168.251.162:8090/download/attachments/5014729/image2019-3-20%2022%3A2%3A59.png?version=1&modificationDate=1553090490000&api=v2)
![](http://192.168.251.162:8090/download/attachments/5014729/image2019-3-20%2022%3A1%3A44.png?version=1&modificationDate=1553090416000&api=v2)
3.3.2 调用creditmng接口,查询消费方接口消费
http://localhost:6002/api/consumer/query?limitId=00000
![](http://192.168.251.162:8090/download/attachments/5014729/image2019-3-20%2022%3A7%3A18.png?version=1&modificationDate=1553090750000&api=v2)
点击try it out,swagger测试结果:
![](http://192.168.251.162:8090/download/attachments/5014729/image2019-3-20%2022%3A7%3A58.png?version=1&modificationDate=1553090790000&api=v2)
3.3.3 shutdown custmng微服务,重新查询
因为微服务默认开启了熔断
#Feign启动okhttp3 feign: httpclient: enabled: false okhttp: enabled: true hystrix: enabled: true |
所以,Feign失败后,会触发熔断逻辑:
[creditmng, 172.16.20.208] WARN 2019-03-14 20:23:12.875 [hystrix-custmng-1, f25a6fb186591006, 8f3e7289a868ad86] cn.com.yusys.yusp.service.impl.LimitInfoServiceHystrix.query:22 - 访问失败,触发熔断 |
响应内容为熔断缺省内容:空字符串,Swagger测试结果:
![](http://192.168.251.162:8090/download/attachments/5014729/image2019-3-20%2022%3A9%3A15.png?version=1&modificationDate=1553090866000&api=v2)
4 进阶
name
和url
属性支持占位符,如
@FeignClient (name = "${feign.name}" , url = "${feign.url}" ) public interface UserProviderService { //.. } |