### OpenFeign 适配器 Sentinel 整合 OpenFeign 主要用于实现熔断降级,因此,关于 OpenFeign 的 Sentinel 适配器的使用介绍基于服务消费端。 #### **使用步骤** **1\. 引入依赖** 借助 spring-cloud-starter-alibaba-sentinel 实现与 OpenFeign 整合,添加依赖配置如下: ~~~ <!-- 熔断限流组件 --> <dependency> <groupId>com.open.capacity</groupId> <artifactId>sentinel-spring-boot-starter</artifactId> </dependency> <!-- 选用nacos时打开--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency> ~~~ **2. 启用 OpenFeign 整合 Sentinel 的自动配置** 在 application.yaml 配置文件中添加如下配置,启用 Sentinel 与 OpenFeign 整合适配器。 ~~~ feign: sentinel: enabled: true ~~~ **3. 编写Feign** ``` package com.open.capacity.uaa.feign; import java.util.Map; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import com.open.capacity.common.auth.details.LoginAppUser; import com.open.capacity.common.feign.FeignExceptionConfig; import com.open.capacity.common.model.SysUser; import com.open.capacity.common.web.PageResult; import com.open.capacity.uaa.feign.fallback.UserFeignClientFallbackFactory; /** * @author 作者 owen * @version 创建时间:2017年11月12日 上午22:57:51 * 调用用户中心中的userdetail对象,用户oauth中的登录 * 获取的用户与页面输入的密码 进行BCryptPasswordEncoder匹配 */ @FeignClient(value="user-center",configuration = FeignExceptionConfig.class ,fallbackFactory = UserFeignClientFallbackFactory.class, decode404 = true) public interface UserFeignClient { /** * feign rpc访问远程/users-anon/login接口 * @param username * @return */ @GetMapping(value = "/users-anon/login", params = "username") LoginAppUser findByUsername(@RequestParam("username") String username); @GetMapping(value = "/users-anon/mobile", params = "mobile") LoginAppUser findByMobile(@RequestParam("mobile") String mobile); @GetMapping(value = "/users", params = "params") PageResult<SysUser> findUsers(@RequestParam Map<String, Object> params); } ``` **4\. 给 @FeignClient 注解配置异常回调** 给接口上的 @FeignClient 注解配置 fallback 属性,实现请求被拒绝后的处理。 ~~~ @FeignClient(value="user-center",configuration = FeignExceptionConfig.class ,fallbackFactory = UserFeignClientFallbackFactory.class, decode404 = true) public interface UserFeignClient { } package com.open.capacity.uaa.feign.fallback; import java.util.Map; import org.springframework.stereotype.Component; import com.open.capacity.common.auth.details.LoginAppUser; import com.open.capacity.common.model.SysUser; import com.open.capacity.common.web.PageResult; import com.open.capacity.uaa.feign.UserFeignClient; import feign.hystrix.FallbackFactory; import lombok.extern.slf4j.Slf4j; @Slf4j @Component public class UserFeignClientFallbackFactory implements FallbackFactory<UserFeignClient> { @Override public UserFeignClient create(Throwable throwable) { return new UserFeignClient() { @Override public LoginAppUser findByUsername(String username) { log.error("通过用户名查询用户异常:{}", username, throwable); return new LoginAppUser() ; } @Override public LoginAppUser findByMobile(String mobile) { log.error("通过手机号查询用户异常:{}", mobile, throwable); return new LoginAppUser(); } @Override public PageResult<SysUser> findUsers(Map<String, Object> params) { log.error("查询用户列表异常:{}"); return null; } }; } } ~~~ **5. Sentinel在给Feign整合时,流控规则编写的形式是 http请求方式://协议://服务名称/请求路径+参数 ** ``` GET:http://user-center/users-anon/login ``` * 配置说明 ![](https://img.kancloud.cn/6a/0d/6a0dccc69eb4d746b2ec8c3c301d0672_1900x908.png) * 流控说明: ![](https://img.kancloud.cn/4b/4e/4b4ea2b853dc37352ec39dc267ae9da2_1886x900.png) #### **Sentinel 与 OpenFeign 整合实现原理** 当 Sentinel 与 OpenFeign、Ribbon 整合时,客户端向服务端发起一次请求的过程如下图所示。 ![](https://img.kancloud.cn/f8/52/f85206983e73eb0e7febbcbbc6419c68_1771x745.png) 1. 当调用@FeignClient 接口的方法时,由 Sentinel 提供的方法调用拦截器(SentinelInvocationHandler)拦截方法的执行,根据接口方法上注解的 url 生成资源名称,然后调用 Sentinel 的 SphU#entry 方法(完成所有 ProcessorSlot#entry 方法的调用),判断当前发起的请求是否需要熔断; 2. 非熔断降级情况下,继续将请求交给 OpenFeign 的 MethodHandler 处理; 3. OpenFeign 从 Ribbon 获取一个服务提供者节点; 4. OpenFeign 使用 HttpClient 发起 HTTP 请求; 5. OpenFeign 请求成功或者异常(已经经过重试)时,调用 Sentinel 的 Entry#exit 方法(完成所有 ProcessorSlot#exit 方法的调用)更新当前时间窗口的请求成功总数、异常总数等指标数据。 Sentinel 处在接口调用的最前端,因此 Sentinel 统计的指标数据即不会受 Ribbon 的重试影响也不会受 OpenFeign 的重试影响。