什么是Feign?
Feign 是一个声明式 WebService 客户端。使用 Feign 能让编写的 WebService 客户端更加简洁,它的使用方法式定义一个接口,然后在上面添加注解。Spring Cloud 对 Feign 进行了封装,使其支持了 Spring MVC 标准注解和 HttpMessageConverters。Feign 可以与 Eureka 和 Ribbon 组合使用以支持负载均衡。
为什么要使用 Feign?
Feign 旨在使编写 Java Http 客户端变得更容易。
使用 Ribbon + RestTemplate 时,利用 RestTemplate 对 http 请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。
所以,Feign 在此基础上做了进一步的封装,由它来帮助我们定义和实现依赖服务接口的定义。使用 Feign 只需要创建一个接口并使用一个注解来配置它即可。这就类似于我们在 dao 层的接口上标注 @Mapper 注解一样。这样的话,即完成了对服务提供方的接口绑定,简化了使用 Spring Cloud Ribbon 时的开发量.
使用如下
声明: @MapperScan("com.xxxx.usercenter.dao") @SpringBootApplication @EnableDiscoveryClient @EnableBinding({Sink.class}) @EnableSwagger2 @ComponentScan("com.xxx") public class UserCenterApplication { public static void main(String[] args) { SpringApplication.run(UserCenterApplication.class, args); } } 配置:
#application.yml配置 ribbon ribbon: eager-load: enabled: true clients: user-center #ribbon的超时时间 ReadTimeout: 5000 ConnectTimeout: 5000
@Configuration public class FeignConfig { @Bean Logger.Level feignLoggerLevel() { return Logger.Level.BASIC; } }
@Slf4j @Configuration public class FeignConfiguration { @Bean public RequestInterceptor headerInterceptor(){ return ((RequestTemplate template)->{ ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); RequestContextHolder.setRequestAttributes(attributes, true); if(attributes == null){ return; } HttpServletRequest request = attributes.getRequest(); Enumeration<String> headerNames = request.getHeaderNames(); if (headerNames != null) { while (headerNames.hasMoreElements()) { String name = headerNames.nextElement(); String values = request.getHeader(name); if(LidThreadLocal.LINK_ID.equals(name)) { LidThreadLocal.setLid(values); log.info("往下传递的LID为:{}",values); } template.header(name, values); } } }); } }
使用:
@Component @Slf4j public class UserCenterFeignClientFallbackFactory implements FallbackFactory<UserCenterFeignClient> { @Override public UserCenterFeignClient create(Throwable cause) { return new UserCenterFeignClient() { @Override public UserDTO findById(Integer id) { log.warn("远程调用 UserCenter 被限流/降级了"); UserDTO userDTO = new UserDTO(); userDTO.setUserName("触发了流控/降级的用户"); return userDTO; } }; } }
@FeignClient(name = "user-center",fallbackFactory = UserCenterFeignClientFallbackFactory.class) public interface UserCenterFeignClient { /** * 通过feign 远程调用 用户中心用户信息 * 相当于http请求: http://user-center/users/{id} * * @param id * @return UserDTO */ @GetMapping("/users/{id}") UserDTO findById(@PathVariable Integer id); }
@MapperScan("com.xxx.billcenter.dao") @SpringBootApplication @EnableFeignClients @EnableBinding({Source.class}) @ComponentScan("com.xxx") @EnableSwagger2 public class BillCenterApplication { public static void main(String[] args) { SpringApplication.run(BillCenterApplication.class, args); } } service调用:
@Slf4j @Service @RequiredArgsConstructor(onConstructor = @__(@Autowired)) public class BillService { private final UserCenterFeignClient userCenterFeignClient; public BillDTO findById(Integer id) { Bill bill = this.billMapper.selectByPrimaryKey(id); Integer userId = bill.getUserId(); // 演示用Feign 调用用户模块 接口 UserDTO userDTO = this.userCenterFeignClient.findById(userId); BeanUtils.copyProperties(bill, billDTO); return billDTO; } }
Feign 如何结合 Ribbon 切换均衡算法
Feign 的使用,很简单,也符合我们平时的接口调用习惯。但是这是默认使用Ribbon的轮询负载均衡算法!
Ribbon和Feign的区别
Ribbon:
是一个基于 HTTP 和 TCP 客户端 的负载均衡的工具。
它可以 在客户端 配置 RibbonServerList(服务端列表),使用 HttpClient 或 RestTemplate 模拟http请求,步骤相当繁琐。
Feign:
Feign 是在 Ribbon的基础上进行了一次改进,是一个使用起来更加方便的 HTTP 客户端。
采用接口的方式, 只需要创建一个接口,然后在上面添加注解即可 ,将需要调用的其他服务的方法定义成抽象方法即可, 不需要自己构建http请求。
然后就像是调用自身工程的方法调用,而感觉不到是调用远程方法,使得编写 客户端变得非常容易。
代码方面的用法区别:
Ribbon:用 REST_URL_PREFIX 指定请求地址 , 使用 restTemplate 模拟 http 请求。也就是说需要自己来构建发起HTTP请求
Feign:
a) 新建一个接口,添加@FeignClient
注解,指定微服务名称 MICROSERVICECLOUD-DEPT
b) 指定请求地址 @RequestMapping
0 条评论