Spring Cloud体系中,远程HTTP调用的常用实现方式有RestTemplate、Feign等。Feign与RestTemplate相比,拥有更好的代码可读性、可维护性,舍弃了部分的灵活性,但是仍能满足绝大多数的需求。
Feign集成Ribbon,feign声明式的web service客户端,让微服务调用变简单,提供负载均衡, feign是一个声明式的HTTP客户端,他的目的就是让远程调用更加简单。给远程服务发的是HTTP请求。简单来说就是调用不同服务的接口,获取数据,因为在传统项目中是不能跨服务获取数据的。
Spring Cloud体系中,远程HTTP调用的常用实现方式有RestTemplate、Feign等。Feign与RestTemplate相比,拥有更好的代码可读性、可维护性,舍弃了部分的灵活性,但是仍能满足绝大多数的需求,引入依赖,添加@EnableFeignClients注解,接下来编写FeignClient接口,在@FeignClient注解中,必须要指定name属性,且Feign内部集成了Ribbon,当name名称为注册的微服务名称时,Feign会调用Ribbon配置的负载均衡规则选择一个微服务实例,并将选中实例的URL拼接至方法前,请求相应的微服务地址。Feign也可以脱离Ribbon使用,在@FeignClient注解中指定url属性,Feign就会使用指定的URL来拼装请求地址。Feign支持代码方式和属性方式两种配置。均支持局部或全局的配置。
Feign的继承,Feign可以通过抽象公共接口,让服务端和客户端分别继承来实现代码重用。但是官方不推荐这么做,因为会导致微服间的紧密耦合。实际项目中可以根据情况灵活使用,此处就不展开讨论,详情可以点击此处了解。
Feign性能优化
Feign默认情况下是使用DefaultClient,集成Ribbon的时候使用的是LoadBalancerFeignClient,底层也是DefaultClient,只是加入了负载均衡规则。而DefaultClient底层是使用的HttpURLConnection来进行请求,是没有连接池支持的。
具体流程:
使用Feign实现远程HTTP调用 首先引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
然后在SpringBoot启动类上添加@EnableFeignClients注解
@SpringBootApplication
@EnableFeignClients
public class ContentCenterApplication {
public static void main(String[] args) {
SpringApplication.run(ContentCenterApplication.class, args);
}
}
接下来编写FeignClient接口
@FeignClient(name = "user-center")
public interface UserCenterFeignClient {
@GetMapping("/users/{id}")
UserDTO findById(@PathVariable Integer id);
}
在@FeignClient注解中,必须要指定name属性,且Feign内部集成了Ribbon,当name名称为注册的微服务名称时,Feign会调用Ribbon配置的负载均衡规则选择一个微服务实例,并将选中实例的URL拼接至方法前,请求相应的微服务地址。
Feign也可以脱离Ribbon使用,在@FeignClient注解中指定url属性,Feign就会使用指定的URL来拼装请求地址。
@FeignClient(name = "test" , url = "www.baidu.com")
public interface UserCenterFeignClient {
@GetMapping("")
String test();
}
//现在,就可以使用Feign来进行HTTP调用
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ShareServiceImpl implements IShareService {
private final @NonNull UserCenterFeignClient userCenterFeignClient;
private final @NonNull ShareMapper shareMapper;
@Override
public ShareDTO findShareById(Integer id) {
Share share = shareMapper.selectByPrimaryKey(id);
UserDTO userDTO = userCenterFeignClient.findById(share.getUserId());
ShareDTO shareDTO = ShareDTO.builder().build();
BeanUtils.copyProperties(share, shareDTO);
shareDTO.setWxNickname(userDTO.getWxNickname());
return shareDTO;
}
}