Feign解读

Feign 简介

FeignNetflix 开发的声明式、模板化的 HTTP 客户端,它使得 HTTP 请求变得更简单,Feign 底层的使用的 HTTP 通信框架是 HttpClientFeign 默认集成了RibbonHystrix,并和 Eureka 结合,默认实现了负载均衡的效果

Feign 的英文表意为“假装,伪装,变形”, 是一个 http 请求调用的轻量级框架,可以以 Java 接口注解的方式调用 Http 请求,而不用像 Java 中通过封装 HTTP 请求报文的方式直接调用。Feign 通过处理注解,将请求模板化,当实际调用的时候,传入参数,根据参数再应用到请求上,进而转化成真正的请求,这种请求相对而言比较直观

Feign 被广泛应用在 springCloud 的解决方案中,是学习基于 springCloud 微服务架构不可或缺的重要组件

开源项目地址:
https://github.com/OpenFeign/feign

Feign 组件的使用示例

导入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

在主启动类上开启 Feign

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients // 在主启动类上开启 Feign 
public class UserApplication {
    
    

	private static final Logger log = LoggerFactory.getLogger(UserApplication.class);

	public static void main(String[] args) {
    
    
		SpringApplication.run(UserApplication.class, args);
		log.info("===============springcloud user启动了=================");
	}
} 

编写服务提供者

@Controller
@RequestMapping(path = {
    
     "/activity" })
public class ActivityController {
    
    

	private static final Logger log = LoggerFactory.getLogger(ActivityController.class);

	@RequestMapping(path = {
    
     "/getCoupon" }, method = RequestMethod.POST)
	@ResponseBody
	public String getCoupon(@RequestBody Integer id) {
    
    
		log.info("=============该用户首次登陆(注册),领取优惠券成功,id的值为:" + id + "============");
		return "SUCCESS";
	}

	@RequestMapping(path = {
    
     "/getCouponTimeOut" }, method = RequestMethod.POST)
	@ResponseBody
	public String getCouponTimeOut(@RequestBody Integer id) {
    
    
		try {
    
    
			Random random = new Random();
			TimeUnit.SECONDS.sleep(random.nextInt(10) % (7) + 4);
		} catch (InterruptedException e) {
    
    
			e.printStackTrace();
		}
		log.info("=============该用户首次登陆(注册),领取优惠券失败============");
		return "ERROR";
	}
}

编写 Feign 调用接口

@FeignClient(name = "STUDY-ACTIVITY", fallback = UserFeignFallback.class)
public interface UserFeign {
    
    

	@RequestMapping(path = {
    
     "/activity/getCoupon" }, method = RequestMethod.POST)
	String getCoupon(@RequestBody Integer id);

	@RequestMapping(path = {
    
     "/activity/getCouponTimeOut" }, method = RequestMethod.POST)
	String getCouponTimeOut(@RequestBody Integer id);

}

fallback 容错的处理类

fallback 容错的处理类:当调用远程接口失败或超时时(默认的超时时间是1000 ms,可以自行设置),会调用对应接口的容错逻辑,fallback 指定的类必须实现 @FeignClient 标记的接口

对于每一个标有注解 @FeignClient 的接口,它下面每一个抽象方法都默认被 Hystrix 包裹了

@Component
public class UserFeignFallback implements UserFeign {
    
    

    @Override
    public String getCoupon(Integer id) {
    
    
    	return null;
    }

    @Override
	public String getCouponTimeOut(Integer id) {
    
    
		return null;
	}
}

使用 Feign 接口的实现类调用远程微服务

@Service
public class UserServiceImpl implements UserService {
    
    

	@Autowired
	private UserFeign userFeign;
 
	@Override
	public String firstLogin(Integer id) {
    
    
		String result = userFeign.getCoupon(id);
		log.info("===================result的值为:" + result + "======================");
		return result;
	}

	@Override
	public String firstLoginTimeOut(Integer id) {
    
    
		String result = userFeign.getCouponTimeOut(id);
		log.info("===================result的值为:" + result + "======================");
		return result;
	}
}

@FeignClient 注解参数

  • @FeignClient 注解被 @Target(ElementType.TYPE) 修饰,表示 FeignClient 注解的作用在目标接口上
  • name:指定 FeignClient 的名称,如果项目使用了 Ribbonname 属性会作为微服务的名称,用于服务发现
  • url:一般用于调试,可以手动指定 @FeignClient 调用的地址
  • decode404:当发生 http 404 错误时,如果该字段位 true,会调用 decoder 进行解码,否则抛出 FeignException
  • configurationFeign 配置类,可以自定义 FeignEncoder、Decoder、LogLevel、Contract
  • fallback:定义容错的处理类,当调用远程接口失败或超时时(默认的超时时间是1000ms,可以自行设置),会调用对应接口的容错逻辑,fallback 指定的类必须实现 @FeignClient 标记的接口
  • fallbackFactory:工厂类,用于生成 fallback 类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码
  • path:定义当前 FeignClient 的统一前缀

Feign 解决了什么问题

封装了 Http 调用流程,更适合面向接口化的编程习惯

在服务调用的场景中,我们经常调用基于 Http 协议的服务,而我们经常使用到的框架可能有 HttpURLConnection、Apache HttpComponnets、OkHttp3 、Netty 等等,这些框架在基于自身的专注点提供了自身特性。而从角色划分上来看,他们的职能是一致的提供Http 调用服务。具体流程如下:

在这里插入图片描述

Feign 是如何设计的

默认情况下,Feign 采用的是 JDKHttpURLConnection 的请求调用框架

在这里插入图片描述

Feign 的工作原理流程

  1. 首先通过 @EnableFeignCleints 注解开启 FeignCleint
  2. 根据 Feign 的规则实现接口,并加 @FeignCleint 注解
  3. 服务启动后,会扫描所有的 @ FeignCleint 的注解的接口,并将这些信息注入到 spring IOC 容器中
  4. 当接口的方法被调用时,会通过 JDK 的动态代理,来生成具体的 RequesTemplate 对象(该对象封装了 HTTP 请求需要的全部信息,包括请求参数名、请求方法等信息,Feign 的模板化就体现在这里)
  5. RequesTemplate 再生成 Request
  6. Request 交给 HttpClient 去处理,其中HttpClientJDKHttpURLConnection
  7. 最后 HttpClient 被封装到 LoadBalanceClient 类,这个类结合类 Ribbon 做到了负载均衡

Feign,Ribbon,Hystrix 三者之间的作用和关系

  • springCloud 微服务体系下,微服务之间的互相调用可以通过 Feign 进行声明式调用,在这个服务调用过程中 Feign 会通过 Ribbon 从服务注册中心获取目标微服务的服务器地址列表,之后在网络请求的过程中 Ribbon 就会将请求以负载均衡的方式打到微服务的不同实例上,从而实现 springCloud 微服务架构中最为关键的功能即服务发现及客户端负载均衡调用
  • 另一方面微服务在互相调用的过程中,为了防止某个微服务的故障消耗掉整个系统所有微服务的连接资源,所以在实施微服务调用的过程中我们会要求在调用方实施针对被调用微服务的熔断逻辑。而要实现这个逻辑场景在 springCloud 微服务框架下我们是通过 Hystrix 这个框架来实现的
  • 调用方会针对被调用微服务设置调用超时时间,一旦超时就会进入熔断逻辑,而这个故障指标信息也会返回给 Hystrix 组件,Hystrix 组件会根据熔断情况判断被调微服务的故障情况从而打开熔断器,之后所有针对该微服务的请求就会直接进入熔断逻辑,直到被调微服务故障恢复,Hystrix 断路器关闭为止

猜你喜欢

转载自blog.csdn.net/weixin_38192427/article/details/113880288
今日推荐