一、前言 线上网络BUG都源于这三点没做好在 iOS 实际项目中比接口报错更可怕的是偶现、难以复现、弱网专属的诡异问题用户地铁弱网点击提交无反馈连续多点后台生成多条重复订单网络抖动瞬间断开又恢复请求无脑重试造成重复点赞、重复上报、重复扣费接口超时时间一刀切首页静态接口超时、支付接口超时体验崩坏断线重连逻辑混乱网络恢复后请求乱飞、回调错乱、页面数据覆盖无法区分「真失败」和「弱网临时失败」导致有效请求被误杀、无效请求疯狂重试绝大多数项目只简单使用 AFN 原生请求没有统一的超时管控、没有智能重连、没有幂等防护线上隐患极大。本文结合百万级用户项目实战经验从零拆解 iOS 网络三层稳定性基石精细化超时策略、智能断线重连、请求幂等设计搭配全套可直接上线的封装代码、业务场景案例、踩坑复盘彻底根治移动端网络不稳定问题同时覆盖高频面试核心考点。二、核心认知三者分工构建网络高可用体系很多开发者混淆三者逻辑其实三者是层层防护、互补兜底的关系共同保障网络请求稳定可靠技术方案核心解决问题适用场景核心目标超时策略解决请求无限挂起、阻塞、卡死问题所有网络请求及时止损避免用户长期等待断线重连解决弱网抖动、临时断网导致的假性失败查询类、静态数据、幂等接口提升弱网成功率无感修复临时网络异常请求幂等解决重复请求、重复提交导致的脏数据、业务错乱提交类、支付类、数据修改类接口保证多次请求业务只生效一次工程核心原则查询接口靠「超时重连」提升体验提交接口靠「幂等禁止重连」保证数据安全。三、精细化超时策略封装告别一刀切超时1. 原生超时的致命缺陷项目高频坑绝大多数项目全局统一设置timeoutInterval 15看似省事实则漏洞百出首页静态接口、文案接口15s 超时太久用户长时间转圈无响应体验极差大文件上传、列表分页接口15s 超时太短正常慢速传输直接被误杀支付、鉴权接口网络波动下频繁超时导致支付失败、登录失效本质原因不同接口的网络压力、传输体量、实时性要求完全不同不能统一超时阈值。2. 两种超时原理深度区分面试实战重点很多开发者分不清 AFN 两个超时参数导致超时规则完全错乱①timeoutIntervalForRequest请求超时推荐使用核心逻辑以「数据包持续传输」为判定标准只要一直在收发数据就不会超时。适合大文件上传下载、大数据列表、弱网慢速传输场景不会误判正常慢速请求。②timeoutIntervalForResource资源超时慎用核心逻辑以「总耗时」为判定标准无论是否传输中到时间直接强制终止。适合小接口、实时接口严格限制总耗时杜绝长期挂起。3. 分级超时策略工程封装可直接上线根据业务场景划分四类超时规则适配 99% 业务需求极速接口首页文案、配置、Banner超时 8s快速失败避免卡顿常规查询接口列表、详情超时 15s平衡速度与稳定性大数据接口分页、批量数据超时 25s容忍慢速传输上传下载接口超时 60s使用请求超时规则不中断持续传输// 统一超时配置工具 分类适配 typedef NS_ENUM(NSInteger, NetworkTimeoutLevel) { NetworkTimeoutLevelFast, // 极速 8s NetworkTimeoutLevelNormal, // 常规 15s NetworkTimeoutLevelBigData, // 大数据 25s NetworkTimeoutLevelFile // 文件传输 60s }; interface AFHTTPSessionManager (TimeoutConfig) - (void)configTimeoutWithLevel:(NetworkTimeoutLevel)level; end implementation AFHTTPSessionManager (TimeoutConfig) - (void)configTimeoutWithLevel:(NetworkTimeoutLevel)level { NSTimeInterval timeout 15; switch (level) { case NetworkTimeoutLevelFast: timeout 8; break; case NetworkTimeoutLevelNormal: timeout 15; break; case NetworkTimeoutLevelBigData: timeout 25; break; case NetworkTimeoutLevelFile: timeout 60; break; default: break; } // 使用请求超时适配弱网慢速传输 self.configuration.timeoutIntervalForRequest timeout; } end // 业务使用示例 - (void)loadHomeBannerData { AFHTTPSessionManager *manager [AFHTTPSessionManager manager]; [manager configTimeoutWithLevel:NetworkTimeoutLevelFast]; // 发起请求... } - (void)uploadBigImage { AFHTTPSessionManager *manager [AFHTTPSessionManager manager]; [manager configTimeoutWithLevel:NetworkTimeoutLevelFile]; // 发起上传... }4. 超时专属错误判定封装区分超时、断网、服务器报错实现精准错误提示提升用户体验 (BOOL)isRequestTimeoutError:(NSError *)error { if (!error) return NO; // AFN 超时错误码-1001 return error.code NSURLErrorTimedOut; } (BOOL)isNetworkDisconnectError:(NSError *)error { if (!error) return NO; // 断网、连接重置、无法连接 NSArray *disconnectCodes [(-1009), (-1005), (-1004), (-1003)]; return [disconnectCodes containsObject:(error.code)]; }四、智能断线重连拒绝无脑重试只重连「可恢复错误」1. 原生重连的两大致命坑点很多项目写死「失败就重试3次」会引发严重线上事故重连风暴全局弱网时所有请求同时重试瞬间压垮服务器加重网络拥堵脏数据产生提交接口、支付接口重试直接导致重复提交、重复扣费2. 智能重连核心规则工程规范严格遵守三不重连、三重连规则从根源规避风险✅ 允许重连临时网络异常可恢复请求超时-1001网络临时断开、链路抖动-1009、-1005服务器临时过载、短暂拒绝连接❌ 禁止重连业务错误不可恢复4xx 参数错误、权限不足、接口不存在5xx 服务器业务报错、数据校验失败支付、提交、修改类非幂等接口3. 指数退避重连算法落地最优弱网方案摒弃固定间隔重试使用指数退避 最大次数限制 网络状态判断兼顾成功率与稳定性重试间隔规则第1次1s、第2次2s、第3次4s阶梯延迟避免风暴// 智能断线重连工具类 interface NetworkReachabilityRetry : NSObject property (nonatomic, assign) NSInteger maxRetryCount; // 最大重试次数默认3 (instancetype)sharedManager; - (void)startRetryWithTask:(NSURLSessionDataTask *(^)(void))task retryNum:(NSInteger)retryNum success:(void (^)(id response))success failure:(void (^)(NSError *error))failure; end implementation NetworkReachabilityRetry (instancetype)sharedManager { static NetworkReachabilityRetry *manager; static dispatch_once_t onceToken; dispatch_once(onceToken, ^{ manager [[self alloc] init]; manager.maxRetryCount 3; }); return manager; } - (void)startRetryWithTask:(NSURLSessionDataTask *(^)(void))task retryNum:(NSInteger)retryNum success:(void (^)(id response))success failure:(void (^)(NSError *error))failure { NSURLSessionDataTask *dataTask task(); [dataTask resume]; dataTask.completionHandler ^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { // 请求成功 if (!error) { success(data); return; } // 超出最大重试次数直接失败 if (retryNum self.maxRetryCount) { failure(error); return; } // 非网络临时异常不重试 if (![self isNeedRetryError:error]) { failure(error); return; } // 指数退避延迟重试 NSTimeInterval delay pow(2, retryNum); NSLog(弱网重试第%ld次延迟%.1fs, retryNum 1, delay); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_global_queue(0, 0), ^{ [self startRetryWithTask:task retryNum:retryNum1 success:success failure:failure]; }); }; } // 精准筛选可重试错误 - (BOOL)isNeedRetryError:(NSError *)error { NSArray *retryCodes [(-1001), (-1009), (-1005), (-1004)]; return [retryCodes containsObject:(error.code)]; } end4. 业务层使用规范强制区分接口类型// 1. 查询类接口允许重连 - (void)loadListData { [[NetworkReachabilityRetry sharedManager] startRetryWithTask:^NSURLSessionDataTask *{ // 发起列表查询请求 } retryNum:0 success:^(id response) { } failure:^(NSError *error) { }]; } // 2. 提交/支付类接口禁止重连直接原生请求 - (void)submitOrder { // 直接发起请求不使用重连工具杜绝重复提交 }五、请求幂等彻底解决重复提交、重复扣费1. 什么是幂等性核心定义幂等性一个接口执行一次 和 执行 N 次对业务数据库的影响完全一致不会产生重复数据、重复操作。移动端 90% 的重复订单、重复点赞、重复上报问题本质都是非幂等接口被重复请求。2. 接口幂等分类业务必须熟记天然幂等接口GET 查询、DELETE 删除、PUT 更新多次请求无副作用非幂等接口POST 提交订单、POST 点赞、POST 上报、POST 支付多次请求产生多条数据风险极高3. 移动端三层幂等防护方案从前端彻底杜绝重复请求服务端幂等依赖后端 Token、唯一键移动端可做三层前置防护拦截 99% 重复请求。第一层UI 防抖拦截最基础、最高频防止用户快速连续点击按钮触发多次请求适配所有提交类按钮// 按钮防抖工具0.8s 冷却期 - (void)buttonClickAction:(UIButton *)sender { sender.userInteractionEnabled NO; // 延迟解锁防止连续点击 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.8 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ sender.userInteractionEnabled YES; }); // 执行提交请求 }第二层请求全局去重核心防护维护当前正在执行的请求列表相同URL相同参数的请求同一时间只允许一个执行自动拦截重复请求。interface NetworkIdempotentManager : NSObject property (nonatomic, strong) NSMutableSet *runningTaskKeys; (instancetype)sharedManager; // 生成请求唯一标识 - (NSString *)taskKeyWithUrl:(NSString *)url params:(NSDictionary *)params; // 判断请求是否重复 - (BOOL)isRepeatTaskWithUrl:(NSString *)url params:(NSDictionary *)params; // 加入/移除执行队列 - (void)addTaskKey:(NSString *)key; - (void)removeTaskKey:(NSString *)key; end implementation NetworkIdempotentManager (instancetype)sharedManager { static NetworkIdempotentManager *manager; static dispatch_once_t onceToken; dispatch_once(onceToken, ^{ manager [[self alloc] init]; manager.runningTaskKeys [NSMutableSet set]; }); return manager; } - (NSString *)taskKeyWithUrl:(NSString *)url params:(NSDictionary *)params { // URL 参数字典排序拼接生成唯一标识 NSArray *sortedKeys [params.allKeys sortedArrayUsingSelector:selector(compare:)]; NSMutableString *paramStr [NSMutableString string]; for (NSString *key in sortedKeys) { [paramStr appendFormat:%%, key, params[key]]; } return [NSString stringWithFormat:%%, url, paramStr]; } - (BOOL)isRepeatTaskWithUrl:(NSString *)url params:(NSDictionary *)params { NSString *key [self taskKeyWithUrl:url params:params]; return [self.runningTaskKeys containsObject:key]; } - (void)addTaskKey:(NSString *)key { synchronized (self.runningTaskKeys) { [self.runningTaskKeys addObject:key]; } } - (void)removeTaskKey:(NSString *)key { synchronized (self.runningTaskKeys) { [self.runningTaskKeys removeObject:key]; } } end第三层幂等 Token 传递前后端统一方案针对支付、订单等高风险接口客户端生成唯一幂等TokenUUID随请求带入服务端根据 Token 去重多次请求只生效一次。// 生成唯一幂等Token NSString *idempotentToken [[NSUUID UUID] UUIDString]; // 放入请求头 [manager.requestSerializer setValue:idempotentToken forHTTPHeaderField:Idempotent-Token];4. 幂等踩坑实战案例故障现象用户弱网点击提交订单转圈无响应再次点击生成两条重复订单。根因POST 订单接口非幂等首次请求后台已执行成功但响应包丢失客户端判定失败二次点击触发重复提交。解决方案按钮防抖 请求去重 幂等Token三重防护彻底杜绝该问题。六、工程统一规范三者组合使用最佳实践结合超时、重连、幂等整理可直接落地的业务接口分级规范团队统一遵循1. 查询类接口首页、列表、详情超时策略分级超时8s/15s重连策略开启指数退避智能重连幂等策略天然幂等无需额外处理2. 数据提交类接口点赞、收藏、上报超时策略15s 常规超时重连策略禁止重连幂等策略UI防抖 全局请求去重3. 核心交易接口订单、支付、充值超时策略20s 加长超时避免正常交易被误杀重连策略严格禁止重连幂等策略三重防护防抖去重幂等Token4. 文件传输接口上传、下载超时策略60s 文件专属超时重连策略开启重连配合断点续传幂等策略文件MD5唯一校验防止重复上传七、高频面试问答必背1. 为什么 POST 接口不允许随意重连POST 多用于数据新增、修改、交易属于非幂等操作多次重试会导致重复提交、重复扣费、脏数据生成严重破坏业务数据一致性。2. 超时 intervalForRequest 和 intervalForResource 区别前者是空闲超时持续传输数据不会超时适合大文件、弱网场景后者是总时长超时到时间强制终止适合实时小接口。3. 移动端如何实现请求幂等三层防护UI 按钮防抖拦截快速点击全局维护请求 Key 去重拦截并行重复请求高风险接口携带唯一幂等 Token服务端兜底去重。4. 指数退避重连的优势是什么相比固定间隔重试可避免弱网下大量请求同时重试造成的重连风暴阶梯延迟逐步退让链路兼顾弱网成功率与服务器稳定性。5. 哪些错误可以重连哪些不能网络临时异常超时、断网、链路抖动可重连业务错误参数错误、权限错误、服务器业务报错不可重连。
iOS 网络工程终极封装:超时策略、智能断线重连、请求幂
一、前言 线上网络BUG都源于这三点没做好在 iOS 实际项目中比接口报错更可怕的是偶现、难以复现、弱网专属的诡异问题用户地铁弱网点击提交无反馈连续多点后台生成多条重复订单网络抖动瞬间断开又恢复请求无脑重试造成重复点赞、重复上报、重复扣费接口超时时间一刀切首页静态接口超时、支付接口超时体验崩坏断线重连逻辑混乱网络恢复后请求乱飞、回调错乱、页面数据覆盖无法区分「真失败」和「弱网临时失败」导致有效请求被误杀、无效请求疯狂重试绝大多数项目只简单使用 AFN 原生请求没有统一的超时管控、没有智能重连、没有幂等防护线上隐患极大。本文结合百万级用户项目实战经验从零拆解 iOS 网络三层稳定性基石精细化超时策略、智能断线重连、请求幂等设计搭配全套可直接上线的封装代码、业务场景案例、踩坑复盘彻底根治移动端网络不稳定问题同时覆盖高频面试核心考点。二、核心认知三者分工构建网络高可用体系很多开发者混淆三者逻辑其实三者是层层防护、互补兜底的关系共同保障网络请求稳定可靠技术方案核心解决问题适用场景核心目标超时策略解决请求无限挂起、阻塞、卡死问题所有网络请求及时止损避免用户长期等待断线重连解决弱网抖动、临时断网导致的假性失败查询类、静态数据、幂等接口提升弱网成功率无感修复临时网络异常请求幂等解决重复请求、重复提交导致的脏数据、业务错乱提交类、支付类、数据修改类接口保证多次请求业务只生效一次工程核心原则查询接口靠「超时重连」提升体验提交接口靠「幂等禁止重连」保证数据安全。三、精细化超时策略封装告别一刀切超时1. 原生超时的致命缺陷项目高频坑绝大多数项目全局统一设置timeoutInterval 15看似省事实则漏洞百出首页静态接口、文案接口15s 超时太久用户长时间转圈无响应体验极差大文件上传、列表分页接口15s 超时太短正常慢速传输直接被误杀支付、鉴权接口网络波动下频繁超时导致支付失败、登录失效本质原因不同接口的网络压力、传输体量、实时性要求完全不同不能统一超时阈值。2. 两种超时原理深度区分面试实战重点很多开发者分不清 AFN 两个超时参数导致超时规则完全错乱①timeoutIntervalForRequest请求超时推荐使用核心逻辑以「数据包持续传输」为判定标准只要一直在收发数据就不会超时。适合大文件上传下载、大数据列表、弱网慢速传输场景不会误判正常慢速请求。②timeoutIntervalForResource资源超时慎用核心逻辑以「总耗时」为判定标准无论是否传输中到时间直接强制终止。适合小接口、实时接口严格限制总耗时杜绝长期挂起。3. 分级超时策略工程封装可直接上线根据业务场景划分四类超时规则适配 99% 业务需求极速接口首页文案、配置、Banner超时 8s快速失败避免卡顿常规查询接口列表、详情超时 15s平衡速度与稳定性大数据接口分页、批量数据超时 25s容忍慢速传输上传下载接口超时 60s使用请求超时规则不中断持续传输// 统一超时配置工具 分类适配 typedef NS_ENUM(NSInteger, NetworkTimeoutLevel) { NetworkTimeoutLevelFast, // 极速 8s NetworkTimeoutLevelNormal, // 常规 15s NetworkTimeoutLevelBigData, // 大数据 25s NetworkTimeoutLevelFile // 文件传输 60s }; interface AFHTTPSessionManager (TimeoutConfig) - (void)configTimeoutWithLevel:(NetworkTimeoutLevel)level; end implementation AFHTTPSessionManager (TimeoutConfig) - (void)configTimeoutWithLevel:(NetworkTimeoutLevel)level { NSTimeInterval timeout 15; switch (level) { case NetworkTimeoutLevelFast: timeout 8; break; case NetworkTimeoutLevelNormal: timeout 15; break; case NetworkTimeoutLevelBigData: timeout 25; break; case NetworkTimeoutLevelFile: timeout 60; break; default: break; } // 使用请求超时适配弱网慢速传输 self.configuration.timeoutIntervalForRequest timeout; } end // 业务使用示例 - (void)loadHomeBannerData { AFHTTPSessionManager *manager [AFHTTPSessionManager manager]; [manager configTimeoutWithLevel:NetworkTimeoutLevelFast]; // 发起请求... } - (void)uploadBigImage { AFHTTPSessionManager *manager [AFHTTPSessionManager manager]; [manager configTimeoutWithLevel:NetworkTimeoutLevelFile]; // 发起上传... }4. 超时专属错误判定封装区分超时、断网、服务器报错实现精准错误提示提升用户体验 (BOOL)isRequestTimeoutError:(NSError *)error { if (!error) return NO; // AFN 超时错误码-1001 return error.code NSURLErrorTimedOut; } (BOOL)isNetworkDisconnectError:(NSError *)error { if (!error) return NO; // 断网、连接重置、无法连接 NSArray *disconnectCodes [(-1009), (-1005), (-1004), (-1003)]; return [disconnectCodes containsObject:(error.code)]; }四、智能断线重连拒绝无脑重试只重连「可恢复错误」1. 原生重连的两大致命坑点很多项目写死「失败就重试3次」会引发严重线上事故重连风暴全局弱网时所有请求同时重试瞬间压垮服务器加重网络拥堵脏数据产生提交接口、支付接口重试直接导致重复提交、重复扣费2. 智能重连核心规则工程规范严格遵守三不重连、三重连规则从根源规避风险✅ 允许重连临时网络异常可恢复请求超时-1001网络临时断开、链路抖动-1009、-1005服务器临时过载、短暂拒绝连接❌ 禁止重连业务错误不可恢复4xx 参数错误、权限不足、接口不存在5xx 服务器业务报错、数据校验失败支付、提交、修改类非幂等接口3. 指数退避重连算法落地最优弱网方案摒弃固定间隔重试使用指数退避 最大次数限制 网络状态判断兼顾成功率与稳定性重试间隔规则第1次1s、第2次2s、第3次4s阶梯延迟避免风暴// 智能断线重连工具类 interface NetworkReachabilityRetry : NSObject property (nonatomic, assign) NSInteger maxRetryCount; // 最大重试次数默认3 (instancetype)sharedManager; - (void)startRetryWithTask:(NSURLSessionDataTask *(^)(void))task retryNum:(NSInteger)retryNum success:(void (^)(id response))success failure:(void (^)(NSError *error))failure; end implementation NetworkReachabilityRetry (instancetype)sharedManager { static NetworkReachabilityRetry *manager; static dispatch_once_t onceToken; dispatch_once(onceToken, ^{ manager [[self alloc] init]; manager.maxRetryCount 3; }); return manager; } - (void)startRetryWithTask:(NSURLSessionDataTask *(^)(void))task retryNum:(NSInteger)retryNum success:(void (^)(id response))success failure:(void (^)(NSError *error))failure { NSURLSessionDataTask *dataTask task(); [dataTask resume]; dataTask.completionHandler ^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { // 请求成功 if (!error) { success(data); return; } // 超出最大重试次数直接失败 if (retryNum self.maxRetryCount) { failure(error); return; } // 非网络临时异常不重试 if (![self isNeedRetryError:error]) { failure(error); return; } // 指数退避延迟重试 NSTimeInterval delay pow(2, retryNum); NSLog(弱网重试第%ld次延迟%.1fs, retryNum 1, delay); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_global_queue(0, 0), ^{ [self startRetryWithTask:task retryNum:retryNum1 success:success failure:failure]; }); }; } // 精准筛选可重试错误 - (BOOL)isNeedRetryError:(NSError *)error { NSArray *retryCodes [(-1001), (-1009), (-1005), (-1004)]; return [retryCodes containsObject:(error.code)]; } end4. 业务层使用规范强制区分接口类型// 1. 查询类接口允许重连 - (void)loadListData { [[NetworkReachabilityRetry sharedManager] startRetryWithTask:^NSURLSessionDataTask *{ // 发起列表查询请求 } retryNum:0 success:^(id response) { } failure:^(NSError *error) { }]; } // 2. 提交/支付类接口禁止重连直接原生请求 - (void)submitOrder { // 直接发起请求不使用重连工具杜绝重复提交 }五、请求幂等彻底解决重复提交、重复扣费1. 什么是幂等性核心定义幂等性一个接口执行一次 和 执行 N 次对业务数据库的影响完全一致不会产生重复数据、重复操作。移动端 90% 的重复订单、重复点赞、重复上报问题本质都是非幂等接口被重复请求。2. 接口幂等分类业务必须熟记天然幂等接口GET 查询、DELETE 删除、PUT 更新多次请求无副作用非幂等接口POST 提交订单、POST 点赞、POST 上报、POST 支付多次请求产生多条数据风险极高3. 移动端三层幂等防护方案从前端彻底杜绝重复请求服务端幂等依赖后端 Token、唯一键移动端可做三层前置防护拦截 99% 重复请求。第一层UI 防抖拦截最基础、最高频防止用户快速连续点击按钮触发多次请求适配所有提交类按钮// 按钮防抖工具0.8s 冷却期 - (void)buttonClickAction:(UIButton *)sender { sender.userInteractionEnabled NO; // 延迟解锁防止连续点击 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.8 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ sender.userInteractionEnabled YES; }); // 执行提交请求 }第二层请求全局去重核心防护维护当前正在执行的请求列表相同URL相同参数的请求同一时间只允许一个执行自动拦截重复请求。interface NetworkIdempotentManager : NSObject property (nonatomic, strong) NSMutableSet *runningTaskKeys; (instancetype)sharedManager; // 生成请求唯一标识 - (NSString *)taskKeyWithUrl:(NSString *)url params:(NSDictionary *)params; // 判断请求是否重复 - (BOOL)isRepeatTaskWithUrl:(NSString *)url params:(NSDictionary *)params; // 加入/移除执行队列 - (void)addTaskKey:(NSString *)key; - (void)removeTaskKey:(NSString *)key; end implementation NetworkIdempotentManager (instancetype)sharedManager { static NetworkIdempotentManager *manager; static dispatch_once_t onceToken; dispatch_once(onceToken, ^{ manager [[self alloc] init]; manager.runningTaskKeys [NSMutableSet set]; }); return manager; } - (NSString *)taskKeyWithUrl:(NSString *)url params:(NSDictionary *)params { // URL 参数字典排序拼接生成唯一标识 NSArray *sortedKeys [params.allKeys sortedArrayUsingSelector:selector(compare:)]; NSMutableString *paramStr [NSMutableString string]; for (NSString *key in sortedKeys) { [paramStr appendFormat:%%, key, params[key]]; } return [NSString stringWithFormat:%%, url, paramStr]; } - (BOOL)isRepeatTaskWithUrl:(NSString *)url params:(NSDictionary *)params { NSString *key [self taskKeyWithUrl:url params:params]; return [self.runningTaskKeys containsObject:key]; } - (void)addTaskKey:(NSString *)key { synchronized (self.runningTaskKeys) { [self.runningTaskKeys addObject:key]; } } - (void)removeTaskKey:(NSString *)key { synchronized (self.runningTaskKeys) { [self.runningTaskKeys removeObject:key]; } } end第三层幂等 Token 传递前后端统一方案针对支付、订单等高风险接口客户端生成唯一幂等TokenUUID随请求带入服务端根据 Token 去重多次请求只生效一次。// 生成唯一幂等Token NSString *idempotentToken [[NSUUID UUID] UUIDString]; // 放入请求头 [manager.requestSerializer setValue:idempotentToken forHTTPHeaderField:Idempotent-Token];4. 幂等踩坑实战案例故障现象用户弱网点击提交订单转圈无响应再次点击生成两条重复订单。根因POST 订单接口非幂等首次请求后台已执行成功但响应包丢失客户端判定失败二次点击触发重复提交。解决方案按钮防抖 请求去重 幂等Token三重防护彻底杜绝该问题。六、工程统一规范三者组合使用最佳实践结合超时、重连、幂等整理可直接落地的业务接口分级规范团队统一遵循1. 查询类接口首页、列表、详情超时策略分级超时8s/15s重连策略开启指数退避智能重连幂等策略天然幂等无需额外处理2. 数据提交类接口点赞、收藏、上报超时策略15s 常规超时重连策略禁止重连幂等策略UI防抖 全局请求去重3. 核心交易接口订单、支付、充值超时策略20s 加长超时避免正常交易被误杀重连策略严格禁止重连幂等策略三重防护防抖去重幂等Token4. 文件传输接口上传、下载超时策略60s 文件专属超时重连策略开启重连配合断点续传幂等策略文件MD5唯一校验防止重复上传七、高频面试问答必背1. 为什么 POST 接口不允许随意重连POST 多用于数据新增、修改、交易属于非幂等操作多次重试会导致重复提交、重复扣费、脏数据生成严重破坏业务数据一致性。2. 超时 intervalForRequest 和 intervalForResource 区别前者是空闲超时持续传输数据不会超时适合大文件、弱网场景后者是总时长超时到时间强制终止适合实时小接口。3. 移动端如何实现请求幂等三层防护UI 按钮防抖拦截快速点击全局维护请求 Key 去重拦截并行重复请求高风险接口携带唯一幂等 Token服务端兜底去重。4. 指数退避重连的优势是什么相比固定间隔重试可避免弱网下大量请求同时重试造成的重连风暴阶梯延迟逐步退让链路兼顾弱网成功率与服务器稳定性。5. 哪些错误可以重连哪些不能网络临时异常超时、断网、链路抖动可重连业务错误参数错误、权限错误、服务器业务报错不可重连。