这是基于vue-vben-admin 模板适用于abp Vnext的前端管理项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

15 KiB

幂等性处理

**本文档中引用的文件** - [AbpIdempotentModule.cs](file://aspnet-core/framework/common/LINGYUN.Abp.Idempotent/LINGYUN/Abp/Idempotent/AbpIdempotentModule.cs) - [AbpIdempotentOptions.cs](file://aspnet-core/framework/common/LINGYUN.Abp.Idempotent/LINGYUN/Abp/Idempotent/AbpIdempotentOptions.cs) - [IdempotentAttribute.cs](file://aspnet-core/framework/common/LINGYUN.Abp.Idempotent/LINGYUN/Abp/Idempotent/IdempotentAttribute.cs) - [IdempotentChecker.cs](file://aspnet-core/framework/common/LINGYUN.Abp.Idempotent/LINGYUN/Abp/Idempotent/IdempotentChecker.cs) - [IdempotentKeyNormalizer.cs](file://aspnet-core/framework/common/LINGYUN.Abp.Idempotent/LINGYUN/Abp/Idempotent/IdempotentKeyNormalizer.cs) - [AbpAspNetCoreMvcIdempotentModule.cs](file://aspnet-core/framework/mvc/LINGYUN.Abp.AspNetCore.Mvc.Idempotent/LINGYUN/Abp/AspNetCore/Mvc/Idempotent/AbpAspNetCoreMvcIdempotentModule.cs) - [AbpIdempotentActionFilter.cs](file://aspnet-core/framework/mvc/LINGYUN.Abp.AspNetCore.Mvc.Idempotent/LINGYUN/Abp/AspNetCore/Mvc/Idempotent/AbpIdempotentActionFilter.cs) - [AbpAspNetCoreMvcIdempotentOptions.cs](file://aspnet-core/framework/mvc/LINGYUN.Abp.AspNetCore.Mvc.Idempotent/LINGYUN/Abp/AspNetCore/Mvc/Idempotent/AbpAspNetCoreMvcIdempotentOptions.cs) - [AbpWrapIdempotentActionFilter.cs](file://aspnet-core/framework/mvc/LINGYUN.Abp.AspNetCore.Mvc.Idempotent.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Idempotent/Wrapper/AbpWrapIdempotentActionFilter.cs) - [IdempotentErrorCodes.cs](file://aspnet-core/framework/common/LINGYUN.Abp.Idempotent/LINGYUN/Abp/Idempotent/IdempotentErrorCodes.cs) - [IdempotentInterceptorRegistrar.cs](file://aspnet-core/framework/common/LINGYUN.Abp.Idempotent/LINGYUN/Abp/Idempotent/IdempotentInterceptorRegistrar.cs)

目录

  1. 简介
  2. 技术架构
  3. 核心组件
  4. 配置方式
  5. 使用场景
  6. 最佳实践
  7. 异常处理
  8. 代码示例
  9. 结论

简介

幂等性处理是确保接口在多次调用时产生相同结果的重要机制,特别是在分布式系统和高并发场景下。LINGYUN.Abp.Idempotent模块提供了完整的幂等性解决方案,通过分布式锁和智能键生成机制,有效防止重复提交和数据不一致问题。该模块支持自动幂等性检查、自定义幂等键生成、灵活的超时配置,并与ABP框架无缝集成。

Section sources

  • README.md

技术架构

幂等性处理模块采用分层架构设计,包含配置层、拦截层、检查层和存储层。该架构通过AOP(面向切面编程)和MVC过滤器实现,确保在不侵入业务代码的情况下提供幂等性保护。

graph TD
A[客户端请求] --> B{请求方法}
B --> |POST/PUT/PATCH| C[AbpIdempotentActionFilter]
B --> |其他方法| D[直接执行]
C --> E[IdempotentKeyNormalizer]
E --> F[生成幂等键]
F --> G[IdempotentChecker]
G --> H[分布式锁检查]
H --> |已存在| I[返回429错误]
H --> |不存在| J[执行业务逻辑]
J --> K[释放分布式锁]
K --> L[返回结果]

**Diagram sources **

  • AbpIdempotentActionFilter.cs
  • IdempotentChecker.cs
  • IdempotentKeyNormalizer.cs

核心组件

幂等性检查器 (IdempotentChecker)

IdempotentChecker是幂等性处理的核心组件,实现了IIdempotentChecker接口。它利用分布式锁机制来确保同一操作在指定时间内只能执行一次。检查器首先验证全局配置是否启用幂等性,然后检查方法是否标记了IgnoreIdempotent属性以决定是否跳过检查。

classDiagram
class IIdempotentChecker {
<<interface>>
+Task<IdempotentGrantResult> IsGrantAsync(IdempotentCheckContext context)
}
class IdempotentChecker {
-IAbpDistributedLock _distributedLock
-AbpIdempotentOptions _idempotentOptions
+Task<IdempotentGrantResult> IsGrantAsync(IdempotentCheckContext context)
}
class IdempotentCheckContext {
+Type Target
+MethodInfo Method
+string IdempotentKey
+IReadOnlyDictionary<string, object> ArgumentsDictionary
}
IIdempotentChecker <|.. IdempotentChecker

**Diagram sources **

  • IIdempotentChecker.cs
  • IdempotentChecker.cs
  • IdempotentCheckContext.cs

Section sources

  • IdempotentChecker.cs

幂等键规范化器 (IdempotentKeyNormalizer)

IdempotentKeyNormalizer负责生成唯一的幂等键,这是幂等性处理的关键。它根据方法的类型、名称和参数生成一个MD5哈希值作为唯一标识。规范化器支持多种键生成策略,包括自定义键、参数映射和默认序列化。

flowchart TD
Start([开始]) --> CheckAttribute{"有IdempotentAttribute?"}
CheckAttribute --> |是| CheckCustomKey{"有自定义键?"}
CheckCustomKey --> |是| UseCustomKey["使用自定义键"]
CheckCustomKey --> |否| UseKeyMap{"有KeyMap?"}
UseKeyMap --> |是| BuildFromKeyMap["根据KeyMap构建"]
UseKeyMap --> |否| BuildFromAllArgs["序列化所有参数"]
CheckAttribute --> |否| BuildFromAllArgs
BuildFromKeyMap --> FormatKey["格式化键: t:type;m:method;k:md5"]
BuildFromAllArgs --> FormatKey
FormatKey --> End([返回幂等键])

**Diagram sources **

  • IdempotentKeyNormalizer.cs
  • IdempotentKeyNormalizerContext.cs

Section sources

  • IdempotentKeyNormalizer.cs

MVC动作过滤器 (AbpIdempotentActionFilter)

AbpIdempotentActionFilter是MVC层面的幂等性实现,作为动作过滤器集成到ASP.NET Core管道中。它负责在控制器动作执行前进行幂等性检查,支持通过HTTP头传递幂等令牌或自动生成。

sequenceDiagram
participant Client as "客户端"
participant Filter as "AbpIdempotentActionFilter"
participant Checker as "IdempotentChecker"
participant Lock as "分布式锁"
Client->>Filter : 发送请求
Filter->>Filter : ShouldCheckIdempotent()
alt 需要检查
Filter->>Filter : 获取幂等键
alt 有X-With-Idempotent-Token头
Filter->>Filter : 使用头中的值
else
Filter->>Filter : 调用IdempotentKeyNormalizer
end
Filter->>Checker : IsGrantAsync()
Checker->>Lock : TryAcquireAsync()
alt 获取锁成功
Lock-->>Checker : 返回锁句柄
Checker-->>Filter : 返回成功结果
Filter->>Client : 执行动作
else
Lock-->>Checker : 返回null
Checker-->>Filter : 返回失败结果
Filter->>Filter : WrapGrantException()
Filter-->>Client : 返回429错误
end
else
Filter->>Client : 直接执行动作
end

**Diagram sources **

  • AbpIdempotentActionFilter.cs
  • AbpAspNetCoreMvcIdempotentModule.cs

Section sources

  • AbpIdempotentActionFilter.cs

拦截器注册器 (IdempotentInterceptorRegistrar)

IdempotentInterceptorRegistrar负责在服务注册时自动为符合条件的服务添加幂等性拦截器。它通过检查服务类型是否实现特定接口或方法是否有Idempotent属性来决定是否应用拦截。

flowchart TD
A[服务注册] --> B[IdempotentInterceptorRegistrar]
B --> C{ShouldIntercept?}
C --> |是| D[添加IdempotentInterceptor]
C --> |否| E[不添加拦截器]
D --> F[服务包含幂等性拦截]
E --> G[服务无幂等性拦截]
subgraph ShouldIntercept逻辑
C --> H{"类型不是忽略类型?"}
H --> |否| I[返回false]
H --> |是| J{"实现ICreateAppService?"}
J --> |是| K[返回true]
J --> |否| L{"实现IUpdateAppService?"}
L --> |是| K
L --> |否| M{"实现IDeleteAppService?"}
M --> |是| K
M --> |否| N{AnyMethodHasIdempotentAttribute?}
N --> |是| K
N --> |否| I
end

**Diagram sources **

  • IdempotentInterceptorRegistrar.cs
  • IdempotentInterceptor.cs

Section sources

  • IdempotentInterceptorRegistrar.cs

配置方式

全局配置

幂等性模块通过AbpIdempotentOptions类提供全局配置选项,可以在模块的ConfigureServices方法中进行配置。

classDiagram
class AbpIdempotentOptions {
+bool IsEnabled
+int DefaultTimeout
+string IdempotentTokenName
+int HttpStatusCode
+AbpIdempotentOptions()
}
note right of AbpIdempotentOptions
默认值 :
- IsEnabled : false
- DefaultTimeout : 5000 (5秒)
- IdempotentTokenName : X-With-Idempotent-Token
- HttpStatusCode : 429 (Too Many Requests)
end

**Diagram sources **

  • AbpIdempotentOptions.cs

Section sources

  • AbpIdempotentOptions.cs

MVC特定配置

AbpAspNetCoreMvcIdempotentOptions提供了MVC特定的配置,主要用于控制哪些HTTP方法需要进行幂等性检查。

classDiagram
class AbpAspNetCoreMvcIdempotentOptions {
+List<string> SupportedMethods
+AbpAspNetCoreMvcIdempotentOptions()
}
note right of AbpAspNetCoreMvcIdempotentOptions
默认支持的方法 :
- POST
- PUT
- PATCH
DELETE方法默认不支持
end

**Diagram sources **

  • AbpAspNetCoreMvcIdempotentOptions.cs

Section sources

  • AbpAspNetCoreMvcIdempotentOptions.cs

模块依赖配置

要使用幂等性功能,需要在模块上添加相应的依赖。

classDiagram
class AbpIdempotentModule {
<<module>>
+PreConfigureServices()
+ConfigureServices()
}
class AbpAspNetCoreMvcIdempotentModule {
<<module>>
+ConfigureServices()
}
class AbpAspNetCoreMvcIdempotentWrapperModule {
<<module>>
}
AbpAspNetCoreMvcIdempotentModule --> AbpIdempotentModule : "依赖"
AbpAspNetCoreMvcIdempotentWrapperModule --> AbpAspNetCoreMvcIdempotentModule : "依赖"
AbpAspNetCoreMvcIdempotentWrapperModule --> AbpAspNetCoreWrapperModule : "依赖"

**Diagram sources **

  • AbpIdempotentModule.cs
  • AbpAspNetCoreMvcIdempotentModule.cs
  • AbpAspNetCoreMvcIdempotentWrapperModule.cs

Section sources

  • AbpIdempotentModule.cs

使用场景

创建操作幂等性

在创建资源的场景中,幂等性可以防止用户重复提交表单导致创建多个相同资源。

sequenceDiagram
participant User as "用户"
participant Browser as "浏览器"
participant API as "API服务"
participant DB as "数据库"
User->>Browser : 点击提交按钮
Browser->>API : POST /api/orders
API->>API : 生成幂等键
API->>API : 检查分布式锁
alt 锁不存在
API->>DB : 创建订单
DB-->>API : 订单ID
API-->>Browser : 201 Created
Browser-->>User : 显示成功
else 锁已存在
API-->>Browser : 429 Too Many Requests
Browser-->>User : 显示重复提交提示
end
User->>Browser : 再次点击提交(误操作)
Browser->>API : POST /api/orders
API->>API : 检查分布式锁
API-->>Browser : 429 Too Many Requests
Browser-->>User : 显示重复提交提示

**Diagram sources **

  • IdempotentChecker.cs
  • AbpIdempotentActionFilter.cs

更新操作幂等性

在更新资源的场景中,幂等性可以确保多次更新请求只产生一次实际更新。

sequenceDiagram
participant Client as "客户端"
participant Service as "服务"
participant Cache as "缓存"
participant DB as "数据库"
Client->>Service : PUT /api/orders/123
Service->>Service : 生成幂等键(order : 123 : update)
Service->>Cache : SETNX order : 123 : update 1 EX 5
alt 设置成功
Cache-->>Service : OK
Service->>DB : UPDATE orders SET ...
DB-->>Service : 更新结果
Service-->>Client : 200 OK
Service->>Cache : DEL order : 123 : update
else 设置失败
Cache-->>Service : 0
Service-->>Client : 429 Too Many Requests
end
Client->>Service : 网络超时, 重试
Service->>Service : 检查幂等键
Service-->>Client : 429 Too Many Requests

**Diagram sources **

  • IdempotentChecker.cs
  • IdempotentKeyNormalizer.cs

分布式环境下的幂等性

在微服务架构中,幂等性确保跨服务调用的一致性。

graph TD
    A[前端服务] --> B[订单服务]
    B --> C[库存服务]
    C --> D[支付服务]
    
    subgraph "幂等性保障"
        B --> E[(Redis分布式锁)]
        C --> E
        D --> E
    end
    
    A -->|创建订单| B
    B -->|检查幂等键| E
    alt 锁不存在
        E -->|获取锁| B
        B -->|扣