高危接口访问熔断机制

简介:

背景介绍

阿里云ECS实例的停机、重启、释放等操作都属于高风险动作,直接影响到ECS实例本身所承载的计算任务和业务。特别是大批量操作时,更加需要明确停机或释放机器的准确性,一旦批量误操作甚至导致整个网站业务线的崩溃。为了防止造成这种巨大损失的局面,针对高风险操作接口提供一种限流熔断机制,批量操作时可以有效的制止过度的错误停机、重启及释放。

设计方案

ECS实例的停机、重启及释放属于高风险操作,未来随着接口应用的深入,其他接口也可能处于高风险状态,例如安全组ACL授权操作等。为了能够让所有高风险操作都可以使用该熔断机制,所以设计的首要原则是高风险接口与熔断机制本身解耦。
需要统计添加熔断机制接口单位时间内的调用频次,设置合理的熔断上限,在不影响日常合理调用的前提下,还需要考虑正常且正确的批量调用,需要提供临时白名单策略。白名单内的用户不受熔断机制限制,需要认真确认实例信息,以免造成大量错误停机、重启或释放的情况。
针对接口熔断类功能需要添加开关进行控制,并逐个地域进行开放,便于观察各接口的熔断情况和调整接口的熔断上限,通关开关的控制可以应对熔断机制带来的突发状况。比如熔断机制不合理,导致接口调用收到严重限制,没有接口只能通过回滚代码的方式进行恢复,时效性低并且存在风险。
设计方案的基本原则:

  • 需要熔断的接口与限流熔断机制之间解耦合;
  • 提供白名单策略,应对超过熔断上限的合理调用;
  • 提供开关策略统一控制各接口的熔断机制;

注解和切面(Annotation+Spect)的方式实现熔断

在不对需要熔断接口的代码做任何修改的前提下,只需要在接口的方法上添加熔断注解就可以实现熔断限流的作用,熔断功能模块独立,接口本身的逻辑和代码独立,通过添加注解的方式实现高内聚低耦合。
首先,定义一个熔断的注解AccessLimit:

/**
 * 高危接口熔断机制
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AccessLimit {}

通过注解@AccessLimit获取方法参数中调用者的信息,实现一个以@AccessLimit为入口的切面,该切面实现了熔断机制的全部逻辑。以调用者的信息作为Key,利用Tair天生Key/Value存储结构的统计该调用者在当前小时内的调用次数,Tair中提供累加的incr方法:

/**
 * @param namespace
 * @param key
 * @param value
 * @param defaultValue
 * @param expireTime
 * @return
 */
Result<Integer> incr(int namespace, Serializable key, int value, int defaultValue, int expireTime);

Tair统计每个调用者Key值过期之前的调用次数,达到熔断上限时抛出异常信息,提示达到风控上线的信息,并不再进一步调用该方法,达到熔断限流的效果。

Tair中incr方法的过期时间

针对同一个调用者,在过期之前的单位时间内,同一方法调用一次访问次数累加一次。incr方法需要注意的是过期时间参数每次调用都会更新的,这样就会存在问题:
1、如果已经达到访问上线,并可以继续执行incr,那么从最后一次访问开始重新记录过期时间。如果在释放Key之前继续访问,将导致该接口针对该用户无法访问。
2、如果已经达到访问上线,并阻止继续执行incr,那么从最后一次访问开始重新记录过期时间,直到该Key过期才能重新继续访问。
以上两种情况统计同一用户对同一接口的访问次数均不准确。解决该问题的方式需要将调用者的Key与当前时间相结合,熔断机制限制方式为每小时N次,任意小时内任何时间取整到小时都是同一个值,将该值与调用者信息拼接作为CacheKey,一天内同一调用者在任意小时内的CacheKey都不一样,这样即使incr方法中的过期时间每次更新,仍然可以准确统计每小时内的访问上线次数。不会出现以上两种请款带来的时间延迟或持续无法访问的情况。关于Key值处理:

/**
 * 获取 cache key
 * @param key
 * @return
 */
private String getCacheKey(String key) {
    Calendar calendar = Calendar.getInstance();
    String hour = String.valueOf(calendar.get(Calendar.HOUR_OF_DAY));
    StringBuilder cacheKey = new StringBuilder(key);
    cacheKey.append("#");
    cacheKey.append(hour)
    return cacheKey.toString();
}

总结

关于接口限流的熔断机制,利用注解和切面的方式进行实现,不仅设计逻辑明确、容易理解,而且很好的体现了高内聚低耦合的设计思想。结合白名单及开关的策略,使得熔断机制的使用更加广泛、安全、灵活。

目录
相关文章
|
4月前
|
安全 搜索推荐 Java
Java系统中的错误码设计问题之确保内外有别并避免暴露敏感数据如何解决
Java系统中的错误码设计问题之确保内外有别并避免暴露敏感数据如何解决
38 0
|
3月前
|
NoSQL 算法 Java
接口限流是一种控制访问频率的技术
在高并发场景下,合理的接口限流、防重复提交及接口防抖机制对保障系统稳定性至关重要。本文介绍了如何利用AOP在不改变业务代码的前提下,灵活添加这些功能。具体包括:通过`@AccessLimit`注解实现接口限流,利用Redis进行计数与控制;通过`@RepeatSubmit`注解防止重复提交,确保数据一致性;通过`@AntiShake`注解实现接口防抖,提升用户体验。此外,提供了基于Redisson和Spring Cloud的实现示例。
51 4
|
4月前
|
负载均衡 调度
异步任务处理系统问题之任务流控的主要目的是什么
异步任务处理系统问题之任务流控的主要目的是什么
|
3月前
|
域名解析 负载均衡 网络协议
Linux网络接口配置不当所带来的影响
总而言之,Linux网络接口的恰当配置是保证网络稳定性、性能和安全性的基础。通过遵循最佳实践和定期维护,可以最大程度地减少配置错误带来的负面影响。
162 0
|
7月前
|
消息中间件 监控 Java
接口请求重试策略:保障稳定性的必杀技
接口请求重试策略:保障稳定性的必杀技
359 0
|
7月前
|
安全 NoSQL Redis
RateLimiter 限流 —— 通过切面对单个用户进行限流和黑名单处理
RateLimiter 限流 —— 通过切面对单个用户进行限流和黑名单处理
120 2
|
7月前
|
监控 测试技术 数据安全/隐私保护
如何集成Sentinel实现流控、降级、热点规则、授权规则总结
如何集成Sentinel实现流控、降级、热点规则、授权规则总结
266 0
|
监控 Dubbo Linux
微服务 热点流控 规则-授权 系统规则 自定义返回
微服务 热点流控 规则-授权 系统规则 自定义返回
102 0
|
算法 NoSQL JavaScript
服务限流,我有6种实现方式…
服务限流,我有6种实现方式…
|
消息中间件 安全 JavaScript
优雅的接口防刷处理方案! 上
优雅的接口防刷处理方案! 上