Feign是Netflix开发的声明式、模板化的的http客户端,它可以帮助我们更快捷、优雅地调用HTTP API。
上一篇文章中,我们使用Ribbon和RestTemplate集成进行请求,但使用Feign后,我们只需要创建一个接口并使用@FeignCilent注解的方式来配置它,即可完成对服务提供方的接口绑定。Feign同时也支持JAX-RS标准的注解,具备可拔插的注解支持,它让微服务之间的调用变得更简单了。
Feign的底层是使用了Ribbon作为负载均衡的客户端,默认继承了Ribbon,而Ribbon的负载均衡也是依赖于Eureka获得各个服务的地址,因此我们与Eureka结合即可实现负载均衡的效果。
一、FeignCilent注解
通过上面的介绍相信大家能发现一个非常关键的东西,那就是我们的注解@FeignClient
。我们要使用Feign进行远程调用,那就离不开这个注解,我们查看这个注解的源码如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FeignClient {
@AliasFor("name")
String value() default "";
/** @deprecated */
@Deprecated
String serviceId() default "";
String contextId() default "";
@AliasFor("value")
String name() default "";
String qualifier() default "";
String url() default "";
boolean decode404() default false;
Class<?>[] configuration() default {};
Class<?> fallback() default void.class;
Class<?> fallbackFactory() default void.class;
String path() default "";
boolean primary() default true;
}
这里我们就不详细描述这个注解的原理,有需要的小伙伴可以去了解一下,在这里我仅将它的一些基本属性列出,方便大家简单的了解以及使用。
属性名 | 默认值 | 作用 | 备注 |
---|---|---|---|
value | 空字符串 | 指定调用服务名称,如果项目使用了Ribbon,会根据属性值去发现服务 | |
name | 空字符串 | 指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现 | |
url | 空字符串 | 一般用于调试程序,允许我们手动指@FeignClient调用的地址 | |
path | 空字符串 | 自动给所有方法的requestMapping前加上前缀(类似于在Controller类上加上@RequestMapping) | |
decode404 | false | 配置响应状态码为404时,如果为true,会调用decoder进行解码,否则抛出FeignException。 | 如果设置为true,需要通过设置configuration去配置decoder |
configuration | {} | Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contract | |
fallback | void.class | 熔断机制,定义容错的处理类,调用失败或超时,会调用对应接口的容错逻辑 | 底层依赖hystrix,启动类要加上@EnableHystrix,且指定的类必须实现@FeignClient标记 |
fallackFactory | void.class | 工场类,用于生成fallback类实例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码 | |
path | 空字符串 | 自动给所有方法的requestMapping前加上前缀(类似于在Controller类上加上@RequestMapping) | |
primary | true | 是否将伪代码标记为主Bean |
二、创建service_feign工程
经过上面的介绍,我们现在就开始动手搭建一个使用Feign的工程,体验一下Feign的优雅与便利!
- 首先我们在原有的工程基础上,创建一个新的Module,还是老规矩,在总工程下选择New Module,填写相关信息,直接点击Next,我们依旧使用idea的快速构建的功能,勾选Spring Cloud Routing -> OpenFeign,如图所示:
后续步骤一直点击Next即可,这里不再多做阐述,搭建好的工程完整如图所示:
- 创建完成完后,我们需要在pom.xml当中加入EurekaClient以及web的依赖,代码如下:
<!--eureka节点依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--web项目依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 修改配置文件,如下:
server.port=8064
spring.application.name=service-feign
#使用health端点来代替心跳表明服务是否可用,反应到eureka server ui上服务的UP还是DOWN
eureka.client.healthcheck.enable=true
eureka.client.service-url.defaultZone=http://127.0.0.1:8761/eureka/
- 然后我们创建一个FeignDaoService的接口,并在该接口上加上@FeignClient的注解,配置value属性对应我们需要调用的服务名称。然后在该接口中添加一个方法,配置@RequstMapping属性,指向我们需要调用的服务中的方法,代码如下:
/**
* @ClassName: FeignDaoService
* @author: Soul
* @Description:
*/
@FeignClient(value = "eureka-client")
public interface FeignDaoService {
/**
* 调用的方法
* @param name
* @return
*/
@RequestMapping(value = "/sayHello", method = RequestMethod.GET)
String sayHeiFromClient(@RequestParam(value = "name") String name);
}
- 接口创建完成后,我们再创建Controller层,调用接口中的方法即可,代码如下:
/**
* @ClassName: FeignDaoController
* @author: Soul
* @Description:
*/
@RestController
public class FeignDaoController {
private static Logger logger = LoggerFactory.getLogger(FeignDaoController.class);
@Autowired
FeignDaoService feignDaoService;
@GetMapping(value = "/feignSayHello")
public String sayHi(@RequestParam String name) {
logger.info("Feign开始进行远程调用=========>参数为:{}", name);
return feignDaoService.sayHeiFromClient(name);
}
}
- 最后我们在启动类上,加上
@EnableDiscoveryClient
以及@EnableFeignClients
两个注解,整个工程就搭建完成了,启动类如下所示:
@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
public class ServiceFeignApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceFeignApplication.class, args);
}
}
- 现在我们可以来验证结果了,依次启动eureka_server、eureka_client、eureka_client2、eureka_feign四个工程,正常启动后我们先打开eureka的控制台,可以发现eureka_client、eureka_client2以及eureka_feign均已注册成功,如图所示:
然后我们可以尝试发送请求,在浏览器中输入http://localhost:8064/feignSayHello?name=soul
,观察发现控制台打印日志如下:
而我们的浏览器交替显示,如图所示:
达到此效果,代表我们使用feign进行远程调用并实现负载均衡成功。