「微服务设计之禅」限流模式

JAVA架构日记

共 2312字,需浏览 5分钟

 ·

2020-12-19 13:39

前言

微服务本质上分布式架构,当我们使用分布式系统时任何不可预知的问题都会发生(例如网络可用性问题、服务可用性问题、中间件可用性问题)。一个系统的问题可能会直接影响另外一个系统的使用或性能。所以在系统设计过程既要保证自身运行的弹性需求,也要避免对下游服务级联故障。

限流模式

在微服务技术架构中,当有多个服务(A,B,C, D)时,一个服务(A)可能依赖于另一服务(B),而另一服务(B)又可能依赖于 C,依此类推。

如下图我们有 2 个服务 A 和 B,B 服务要进行大量的业务计算和其他依赖接口调用导致 B 的最大请求处理个数小于请求 A 的并发数。

当服务 A 接收到很多的服务请求时,由于 B 服务能够处理的请求数量多,从而导致服务宕机。

作为服务 B 为了保证自身高,通过拒绝无法处理的请求来保证服务正常运行。

限流模式通过限制在指定时间窗内运行的请求处理数量,帮助提升服务的可用性。

示例程序

架构图

如上图所示,简单模拟电商下单逻辑

  • 用户登录浏览商品 (商品库存模块)
  • 扣减商品库存 (商品库存模块)
  • 创建商品订单 (订单模块)

product-service 通过调用 order-service 服务下单

代码实现

├── ratelimiter-demo
   ├── order-service        #订单服务  (8070)
   └── product-service      #商品库存服务  (8050)
  • 依赖说明。由于 hystrix 年久失修,这里使用 resilience4j 断路保护器做演示
<dependency>
    <groupId>io.github.resilience4jgroupId>
    <artifactId>resilience4j-spring-boot2artifactId>
    <version>1.6.1version>
dependency>
  • 针对接口定义重试策略 10s 内最多允许通过 5 个请求
resilience4j.ratelimiter:
  instances:
    createOrder:
      limitForPeriod: 5        # 最多运行多少个
      limitRefreshPeriod: 10s  #时间窗限制 10s
  • 消费方接口。product-service 8050
/**
 * 用户点击购买
 */

@SneakyThrows
@GetMapping("/order")
public String buy() {
    // 模拟调用 订单服务下单
    orderService.createOrder().get();
    return "success";
}
  • 定义远程调用类使用 Retry 包装
/**
 * 创建订单
 * name: 指定接口限流配置名称
 * fallbackMethod: 限流后降级方法
 */

@RateLimiter(name = "createOrder", fallbackMethod = "getError")
public CompletableFuture createOrder() {
    return CompletableFuture.supplyAsync(() -> restTemplate.getForEntity("http://localhost:8070/createOrder"
            , String.class).getBody());
}

public CompletableFuture getError(Throwable error) {
    log.warn("创建订单失败了 {}", error.getMessage());
    throw new RuntimeException("创建订单失败了");
}

    • 服务提供方。order-service 8070
@RestController
public class PayController {
    @SneakyThrows
    @GetMapping("/createOrder")
    public String createOrder() {
        return "创建订单服务";
    }
}

开始测试

  • 并发 10 个线程,请求商品服务 (由于我们设置策略 10 秒内只允许 5 个请求)
  • 订单服务日志,由于是第一次请求触发异常,然后服务调用方自动重试产生第二次调用。
2020-12-07 15:53:46.698  WARN 52265 --- [nio-8050-exec-6] c.example.product.service.OrderService   : 创建订单失败了 RateLimiter 'createOrder' does not permit further calls

... 异常日志 ...

源码:https://github.com/lltx/microservices-pattern

参考资料和部分图片来源 https://www.vinsguru.com

往期推荐

「微服务设计之禅」重试模式

「微服务设计之禅」超时模式

「微服务设计之禅」隔离模式

「2020封箱」Spring Boot 2.4.1 发布

「SpringBoot 新特性」启动耗时详细监控

Spring Boot Xss 攻击过滤插件

「Spring Boot 新特性」 jar 大小自动瘦身



浏览 65
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报