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;
    }
}