侧边栏壁纸
博主头像
拾荒的小海螺博主等级

只有想不到的,没有做不到的

  • 累计撰写 140 篇文章
  • 累计创建 15 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

架构师:深入了解Feign简化微服务通信

拾荒的小海螺
2024-07-30 / 0 评论 / 0 点赞 / 19 阅读 / 7596 字

1、简述

Feign 是 Netflix 公司开发的一个声明式的 REST 调用客户端(调用远程的restful风格的http接口 的一个组件);是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求,而不用像Java中通过封装HTTP请求报文的方式直接调用。Feign通过处理注解,将请求模板化,当实际调用的时候,传入参数,根据参数再应用到请求上,进而转化成真正的请求,这种请求相对而言比较直观。

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

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

2、Feign设计

Feign 在默认情况下,采用的JDK的HttpURLConnection调用,是一种声明式的调用方式,它的使用方法是定义一个接口,然后在接口上添加注解,使其支持了Spring MVC标准注解和HttpMessageConverters,Feign可以与Eureka和Ribbon组合使用以支持负载均衡。
常用的http组件:
A、Httpclient(apache)
B、Httpurlconnection (jdk)
C、restTemplate(spring)
D、OkHttp3 (android)
E、Feign (Netflix)

对比其他http组件,Feign调用简单,代码量最少,但是仅支持最常用的调用。

Feign的设计图解:

1722304735356.jpg

通过以上图解,可以看出动态代理起到核心的作用,当客户端发起Feign注解修饰请求,由动态代理类接管,通过对请求和返回数据的加密和解密,得到最终的结果。

3、负载均衡

SpringCloud微服务常用的远程调用Feign+Ribbon来实现负载均衡:

1722304754429.jpg

微服务启动时,会向Eureka服务注册中心注册服务实例, 每个实例包括:IP地址、端口号信息。

客户端会定期从Eureka Server(服务发现中心)获取服务实例列表。当客户端调用Service A实例时,Ribbon组件从本地服务实例列表中查找Service A的实例,并获取Service A ,Service B 中的接口实例。这时Ribbon会通过用户所配置的负载均衡策略从中选择一个实例。

最终,Feign组件会通过Ribbon负载均衡策略选取的实例发送Http请求。

4、Feign集成

4.1 Feign依赖

集成feign,要先导入openfeign到pom.xml中:

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

4.2、Feign接口

在shop-order项目中添加产品的feign接口,并指定调用接口服务地址value:

/**
 * @author lsk
 * @version 1.0.0
 * @ClassName ProductFeignService.java
 * @Description 产品feign服务接口
 * @createTime 2022年11月02日 00:05:00
 */
@FeignClient(value = "SHOP-PRODUCT")
public interface ProductFeignService {
    @GetMapping("/product/getProductById/{id}")
     R getProductById(@PathVariable("id") Long id);
}

4.3 Feign客户端注册

在调用的shop-order启动类中添加@EnableFeignClients 启动注解:

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableFeignClients(basePackages = "com.lm.shop.order.feign")
public class ShopOrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ShopOrderApplication.class, args);
    }
}

4.4 Feign接口调用

跟正常服务接口调用一样引入:

/**
 * @author lsk
 * @version 1.0.0
 * @ClassName OrderController.java
 * @Description 订单控制层
 * @createTime 2022年10月19日 19:17:00
 */
@RestController
@RequestMapping("sku")
public class SkuController {

    @Autowired
    ProductFeignService productFeignService;

    @GetMapping("/getOrder")
    public R getOrder(){
        return this.productFeignService.getProductById(2L);
    }
}

调用成功返回我们所需数据:
在这里插入图片描述

5、Feign配置

5.1 超时时间

Feign默认的超时时间是两秒,所以调试断点的时候要注意,有可能超时导致调用失败,可以自己定义超时时间:

feign.httpclient.connection-timeout=10000

5.2 熔断器

Feign集成了集成Hystrix熔断器,所以我们可以通过配置来开启他的熔断,默认是关闭的,保证接口的稳定性:

feign.hystrix.enabled=true

添加ProductFeignServiceImpl类来生成熔断接口数据处理:

/**
 * @author lsk
 * @version 1.0.0
 * @ClassName ProductFeignServiceImpl.java
 * @Description 产品熔断接口
 * @createTime 2022年11月03日 00:47:00
 */
@Component
public class ProductFeignServiceImpl implements ProductFeignService {  
    /**
     * @title getProductById
     * @description 获取产品信息的熔断方法
     * @author lsk 
     * @param: id
     * @updateTime 2022/11/3 0:48 
     * @return: com.lm.shop.common.utils.R
     */
    @Override
    public R getProductById(Long id) {
        return R.ok().setData(id);
    }
}

在FeignClient注解中添加熔断实现类:

/**
 * @author lsk
 * @version 1.0.0
 * @ClassName ProductFeignService.java
 * @Description 产品feign服务接口
 * @createTime 2022年11月02日 00:05:00
 */
@FeignClient(value = "SHOP-PRODUCT", fallback = ProductFeignServiceImpl.class)
public interface ProductFeignService {

    @GetMapping("/product/getProductById/{id}")
     R getProductById(@PathVariable("id") Long id);

}

5.3 http切换

Feign集成不同的Http组件,可以通过配置切换:

feign.httpclient.enabled=true
feign.okhttp.enabled=true

5.4 数据压缩

SpringCloudFeign支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。
通过配置开启请求与响应的压缩功能:

feign.compression.request.enabled=true
feign.compression.response.enabled=true

同时可以设置压缩的数据格式和压缩的数据大小:

feign.compression.request.mime-types=text/html,application/xml,application/json
feign.compression.request.min-request-size=2048

6、Feign session传递

在多线程远程调用的Feign接口,容易导致Cookie丢失,需要重新设置Cookie。

RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
//3、Sku销售组合属性
CompletableFuture<Void> saleFuture = infoFuture.thenAcceptAsync((res) -> {
   //TODO
   RequestContextHolder.setRequestAttributes(attributes);
});

在拦截器中重新赋值Cookie:

@Configuration
public class MyFeignConfig {
    @Bean("requestInterceptor")
    public RequestInterceptor requestInterceptor(){
        return new RequestInterceptor() {
            @Override
            public void apply(RequestTemplate requestTemplate) {
                ServletRequestAttributes attributes = (ServletRequestAttributes ) RequestContextHolder.getRequestAttributes();
                HttpServletRequest request = attributes.getRequest();
                if(request != null){
                    String cookie = request.getHeader("Cookie");
                    requestTemplate.header("Cookie", cookie);
                }
            }
        };
    }
}

7、结语

Feign是构建简洁、高效微服务架构的重要工具,通过其声明式的方式来定义HTTP客户端,可以使得服务之间的通信变得更加简单和优雅。如果你正在构建一个微服务架构,不妨考虑使用Feign来简化微服务通信的过程。
项目Gitee:https://gitee.com/lhdxhl/lhdx-shop.git

0

评论区