[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-strapi-article:zh:website-regional-date-time-display-testing":3,"blog-article:\u002Fblog\u002Fwebsite-regional-date-time-display-testing":690,"blog-related:\u002Fblog\u002Fwebsite-regional-date-time-display-testing":691,"blog-translations:\u002Fblog\u002Fwebsite-regional-date-time-display-testing":692},{"available":4,"article":5,"relatedArticles":194,"translations":563},true,{"source":6,"id":7,"documentId":8,"translationKey":8,"locale":9,"slug":10,"path":11,"_path":11,"title":12,"description":13,"excerpt":13,"image":14,"publishedAt":15,"updatedAt":16,"author":17,"tags":18,"featured":19,"sortOrder":20,"readingTime":21,"bodyType":22,"bodyBlocks":23,"bodyHtml":193},"strapi",3593,"ogy412lschc3rxvvo063hdwi","zh","website-regional-date-time-display-testing","\u002Fblog\u002Fwebsite-regional-date-time-display-testing","国际站日期时区显示测试：固定时间戳与边界","国际站日期时区显示测试固定同一时间戳，分别核对业务时区、设备时区与页面格式，覆盖 UTC 跨日与夏令时边界，并记录时区 ID 与出口地区。","https:\u002F\u002Fcms.quanqiudaili.com\u002Fuploads\u002Flarge_website_regional_date_time_display_testing_1_b8ccc61802.webp","2026-10-23T03:44:12.011Z","2026-10-23T03:44:11.996Z","Global Proxies Team",[],false,0,3,"blocks",[24,30,36,40,44,48,52,56,60,64,68,72,77,81,85,89,93,97,101,105,109,113,117,121,125,129,133,137,141,145,149,153,157,161,165,169,173,177,181,185,189],{"type":25,"children":26},"paragraph",[27],{"text":28,"type":29},"日期显示错一天，往往不是格式化写错了，而是时区在某一层被换算了两次，或者跨日边界落在了错误的一侧。国际站日期时区显示测试的关键是控制变量：同一时间戳、明确的设备时区、明确的页面语言，然后看页面怎么呈现。这类差异只在特定地区出现时才需要真实出口，出口可由原生静态住宅代理 IP 提供，但它只决定\"从哪访问\"；IP 地区不是设备时区，页面读到的是设备或账号的时区设置，两者不能混为一谈。下面按固定时间戳、边界值和记录口径三步走。","text",{"type":31,"level":32,"children":33},"heading",2,[34],{"text":35,"type":29},"固定时间戳，每次只改变一个时区变量",{"type":25,"children":37},[38],{"text":39,"type":29},"先选一个确定的时间点，比如 `2026-03-08T07:30:00Z`，写进用例。每次只改一个变量：设备时区、页面语言、账号地区，三者轮换，其余保持不变。",{"type":25,"children":41},[42],{"text":43,"type":29},"三个变量各自影响什么要分清：设备时区决定\"本地时间\"的换算，页面语言决定格式（月\u002F日顺序、分隔符、12 或 24 小时制），账号地区可能决定业务时区，例如报表按哪个时区归日。三者叠加时，页面显示的是哪一个，必须能被单独验证。",{"type":25,"children":45},[46],{"text":47,"type":29},"出口地区属于环境变量，设备时区和业务时区属于配置变量。两者混着改，最后分不清是代理 IP 变了还是时间源变了。",{"type":25,"children":49},[50],{"text":51,"type":29},"常见错误是只改语言就断言\"时区也对\"。语言与时区是两套配置，在很多实现里根本不在同一处读取。",{"type":25,"children":53},[54],{"text":55,"type":29},"还要先分清三类值：事件时刻（带时区，可换算）、纯日期（生日、营业日、账期日，不带时刻）、本地预约时间（用户在该地区选的钟点）。纯日期一旦被转成 UTC 再按设备时区显示，会人为跨日——`2026-03-08` 在东九区可能显示成 3 月 7 日。表里\"值类型\"一列就是给这件事留的：纯日期按原值比较，不参与时区换算。",{"type":31,"level":32,"children":57},[58],{"text":59,"type":29},"检查 UTC 跨日和夏令时切换",{"type":25,"children":61},[62],{"text":63,"type":29},"如果跨地区对比还出现页面内容变化，可按[国际站地区页面差异判定](https:\u002F\u002Fwww.quanqiudaili.com\u002Fblog\u002Fregional-page-difference-regression-testing)核对差异是否属于预期配置。",{"type":31,"level":21,"children":65},[66],{"text":67,"type":29},"用哪些日期覆盖常见时间边界",{"type":25,"children":69},[70],{"text":71,"type":29},"至少覆盖四类：UTC 跨日（本地时间已进入次日）、本地午夜前后各一分钟、夏令时开始那天的缺失小时、夏令时结束那天的重复小时。常规值过了不代表边界能过。",{"type":73,"children":74},"code",[75],{"text":76,"type":29},"| 场景 | 值类型 | 输入时间戳（示例） | 设备时区 | 期望显示 | 结论 |\n| --- | --- | --- | --- | --- | --- |\n| UTC 跨日 | 事件时刻 | `2026-03-08T23:30:00Z` | 东九区 | 次日 08:30 | 通过 |\n| 本地午夜前 | 事件时刻 | `2026-03-08T14:59:00Z` | 东九区 | 当日 23:59 | 通过 |\n| 夏令时开始前 1 分钟 | 事件时刻 | `2026-03-08T06:59:00Z` | 美东 | 当日 01:59（EST，偏移 −5） | 通过 |\n| 夏令时开始瞬间 | 事件时刻 | `2026-03-08T07:00:00Z` | 美东 | 当日 03:00（EDT，偏移 −4） | 通过，2 点整点不存在 |\n| 夏令时结束前 | 事件时刻 | `2026-11-01T05:30:00Z` | 美东 | 当日 01:30（EDT） | 通过，第一次 01:30 |\n| 夏令时结束后 | 事件时刻 | `2026-11-01T06:30:00Z` | 美东 | 当日 01:30（EST） | 通过，第二次 01:30 |\n| 月末跨日 | 事件时刻 | `2026-03-31T23:30:00Z` | 东九区 | 次月 1 日 08:30 | 通过（账期按业务时区归日） |",{"type":25,"children":78},[79],{"text":80,"type":29},"同一墙上时间 01:30 在一小时内出现两次，UTC 值不同、显示值相同——这正是必须用 UTC 记录的原因。若要验证\"用户输入不存在的本地时间\"（如 02:30），另列无偏移输入，并写明策略是拒绝、取早还是取晚。",{"type":25,"children":82},[83],{"text":84,"type":29},"这两类边界要固定 UTC 基准值与设备时钟，分别核对系统时区、账号\u002F业务时区、接口返回的时间值与格式化配置。真实地区出口只能验证\"IP 是否参与业务时区选择\"这一条，用它排除不了设备时间错误。",{"type":31,"level":21,"children":86},[87],{"text":88,"type":29},"记录时区数据库版本，避免结果漂移",{"type":25,"children":90},[91],{"text":92,"type":29},"记录里带上运行时使用的时区数据库版本（IANA tzdata）。版本升级会改变跳变规则与历史偏移；同一份用例换个环境跑出不同结果时，先比对这一项。",{"type":25,"children":94},[95],{"text":96,"type":29},"时间戳统一用 UTC 记录，页面显示按本地时区换算。不要在用例里写\"下午三点\"这种相对表述，否则第二天就无法复现。",{"type":31,"level":32,"children":98},[99],{"text":100,"type":29},"检查“几分钟前”等相对时间显示",{"type":25,"children":102},[103],{"text":104,"type":29},"绝对时间的边界清楚了，相对时间还有一套自己的坑。",{"type":25,"children":106},[107],{"text":108,"type":29},"\"3 分钟前\"\"昨天\"\"下周三\"这类相对时间，依赖当前时间与基准时区。测试时要能冻结时钟：发布时刻、当前时刻、基准时区三个值都写死，结果才有断言可比。",{"type":25,"children":110},[111],{"text":112,"type":29},"跨日措辞最容易出问题：内容发布于 `2026-03-08T23:58Z`、当前时刻 `2026-03-09T00:01Z`，UTC 下发布日是 3 月 8 日、当前是 3 月 9 日，相对语义为\"昨天\"；东九区两者都落在 3 月 9 日，同一天，应显示\"今天\"。两个断言都按冻结时钟写，而不是看着像就过。",{"type":25,"children":114},[115],{"text":116,"type":29},"绝对时间与相对时间在同一页面共存时，要检查两者是否指向同一时刻。常见缺陷是列表用相对时间、详情用绝对时间，且换算基准不同。",{"type":31,"level":32,"children":118},[119],{"text":120,"type":29},"记录时区 ID，避免城市名含糊",{"type":25,"children":122},[123],{"text":124,"type":29},"遇到目标地区没有独立页面的情况，可参照[国际站回退体验测试](https:\u002F\u002Fwww.quanqiudaili.com\u002Fblog\u002Finternational-site-locale-fallback-testing)核对回退结果。",{"type":25,"children":126},[127],{"text":128,"type":29},"记录里写 `Asia\u002FTokyo`、`America\u002FNew_York` 这类 IANA 时区 ID，不要只写\"东京\"\"纽约\"。城市名在夏令时、历史时区变更和别名上都有歧义，ID 才能精确复现。",{"type":25,"children":130},[131],{"text":132,"type":29},"差一天时要按层比对，而不是直接改代码：先看数据库时间戳，再看接口序列化结果，然后是浏览器时区，最后才是格式化逻辑。顺序颠倒会把格式化问题误判成存储问题。",{"type":25,"children":134},[135],{"text":136,"type":29},"同时记录设备时区、账号地区、页面语言三项的实际值，以及页面最终采用的时区来源。只写\"已切换到某地区\"，无法判断页面到底按哪个时区渲染。",{"type":25,"children":138},[139],{"text":140,"type":29},"结论里要区分\"格式问题\"与\"时刻问题\"：格式问题改本地化配置，时刻问题查换算链路，两者修复路径完全不同。",{"type":25,"children":142},[143],{"text":144,"type":29},"地区识别结果与设备设置不一致时，排查口径见代理 IP 地区、时区与语言一致性。",{"type":31,"level":32,"children":146},[147],{"text":148,"type":29},"FAQ",{"type":31,"level":21,"children":150},[151],{"text":152,"type":29},"改了代理 IP 地区，页面时间会跟着变吗？",{"type":25,"children":154},[155],{"text":156,"type":29},"通常不会。IP 地区影响的是地区识别，时间显示多由设备时区、账号设置或业务时区决定。要验证这一点，固定设备时区、只换出口再看结果。",{"type":31,"level":21,"children":158},[159],{"text":160,"type":29},"日期格式和时区是一回事吗？",{"type":25,"children":162},[163],{"text":164,"type":29},"不是。格式由语言与区域设置决定，时区决定换算后的小时。只改其中一个，另一项不会自动正确。",{"type":31,"level":21,"children":166},[167],{"text":168,"type":29},"夏令时那天少了一小时，算缺陷吗？",{"type":25,"children":170},[171],{"text":172,"type":29},"要区分。缺失小时是时区规则本身的结果，属于预期；但页面显示的时间与预期换算不一致，就是缺陷。",{"type":31,"level":21,"children":174},[175],{"text":176,"type":29},"测时区必须换出口吗？",{"type":25,"children":178},[179],{"text":180,"type":29},"大多数日期问题本地即可复现，只要设备时区可控。只有当站点按访问地区决定业务时区时，才需要真实地区出口，可优先评估原生静态住宅代理 IP。",{"type":25,"children":182},[183],{"text":184,"type":29},"固定地区会话的产品说明可参见[静态住宅 FAQ](https:\u002F\u002Fhelp.quanqiudaili.com\u002Fdocs\u002FFaq\u002FStatic-Residence-Faq)。",{"type":25,"children":186},[187],{"text":188,"type":29},"对比地区渲染结果时，可结合国际站地区页面差异判定，区分预期配置和时间显示缺陷。这一轮留下的是一份\"时间戳—时区 ID—显示值\"的三列对照表，不是一句\"时区没问题\"。",{"type":25,"children":190},[191],{"text":192,"type":29},"若业务时区依赖访问地区、需要按地区稳定复现，可按地区与会话要求评估[原生静态住宅代理 IP](https:\u002F\u002Fwww.quanqiudaili.com\u002Fproduct\u002Fstatic-residential-native)，产品规则仍需在自有测试环境验证。","",[195,323,443],{"source":6,"id":196,"documentId":197,"translationKey":197,"locale":9,"slug":198,"path":199,"_path":199,"title":200,"description":201,"excerpt":202,"image":203,"publishedAt":204,"updatedAt":205,"author":17,"tags":206,"featured":19,"sortOrder":20,"readingTime":21,"bodyType":22,"bodyBlocks":207,"bodyHtml":193},3656,"ekifxujrbn3ntaau1tjbmimb","saas-regional-issue-ticket-reproduction-fields","\u002Fblog\u002Fsaas-regional-issue-ticket-reproduction-fields","SaaS 地区问题工单模板怎么写？快速复现字段清单","SaaS 地区问题工单应记录复现步骤、期望与实际、地区和版本、发生时间、请求标识及脱敏证据，帮助团队判断问题层级并复现现象。","SaaS 地区问题工单应记录复现步骤、期望与实际、地区和版本、发生时间、请求标识及脱敏证据，帮助团队判断问题层级并复现现象。\n\n","https:\u002F\u002Fcms.quanqiudaili.com\u002Fuploads\u002Flarge_saas_cover_c45f338688.webp","2026-10-26T09:51:28.641Z","2026-10-26T09:51:28.627Z",[],[208,212,216,220,224,228,232,236,240,244,248,252,256,260,264,268,272,276,280,284,288,291,295,299,303,307,311,315,319],{"type":25,"children":209},[210],{"text":211,"type":29},"工单先描述现象和复现条件，再补期望结果、实际结果、版本、地区与请求标识。字段齐全能减少补充沟通，但最终分派仍应由团队依据证据判断；下文提供可按需采用的模板。本文把通用缺陷报告的字段细化到地区问题，不另建一套通用 QA 报告规范。",{"type":31,"level":32,"children":213},[214],{"text":215,"type":29},"先把现象写到可以复现",{"type":25,"children":217},[218],{"text":219,"type":29},"如果工单只写“某地区打不开”，接单团队通常还需要追问复现条件。先描述请求发生在哪个环节，再补足版本、地区、期望和实际结果，能帮助团队更快判断由谁继续处理。",{"type":25,"children":221},[222],{"text":223,"type":29},"例如，“某地区打不开”可以补成：“在测试地区 A 使用版本 2.4.1 提交注册，页面返回 500；尝试 10 次复现 9 次，Trace ID 已附，预期应进入邮箱验证。”这是虚构格式示例，实际工单应填写真实测试记录并脱敏。",{"type":31,"level":21,"children":225},[226],{"text":227,"type":29},"先说明问题可能属于网络、配置、数据还是产品逻辑",{"type":25,"children":229},[230],{"text":231,"type":29},"网络、配置、数据或产品问题可作为初步分诊方向，证据不足时标记“待确认”。分诊层级能帮助确定初始接单团队，但响应时限应以团队公开的支持流程为准。若问题发生在注册限制或提示环节，可参考[多地区注册测试](https:\u002F\u002Fwww.quanqiudaili.com\u002Fblog\u002Fsaas-multi-region-signup-restriction-testing)补充账户状态和规则命中信息。",{"type":31,"level":32,"children":233},[234],{"text":235,"type":29},"一份能直接派单的工单长这样",{"type":25,"children":237},[238],{"text":239,"type":29},"下面给出一组字段示例。各团队可按内部流程调整必填项，并避免把敏感凭证写入工单。",{"type":73,"children":241},[242],{"text":243,"type":29},"| 字段 | 是否必填 | 填写示例 | 缺了会怎样 |\n|---|---|---|---|\n| 分诊层级 | 必填 | 疑似应用层（接口 500） | 初始接单团队要重新判断 |\n| 复现步骤（测试步骤） | 必填 | 1 登录 2 选地区 3 提交 4 报错 | 处理人无法独立重现 |\n| 期望与实际 | 必填 | 期望创建成功，实际提示地区不可用 | 无法判断是否算缺陷 |\n| 出现频率 | 必填 | 记录已知复现次数、尝试次数及观察窗口；暂时无法统计时注明“总尝试次数未知” | 偶发问题难定级 |\n| 首次出现时间 | 必填 | 记录日期、时间与 UTC 偏移 | 难以与发布记录对齐 |\n| 请求 ID（Trace ID） | 有则填写 | 填写 Trace ID；没有时记录可定位的请求时间 | 无法关联日志；没有 Trace ID 时可用时间、入口等可关联信息并注明 |\n| 环境\u002F版本 | 必填 | 产品版本、客户端版本、测试地区 | 无法确认复现条件 |\n| 出口与网络 | 视问题填写 | 测试地区、网络类型及检测时间 | — |\n| 脱敏状态 | 提交前必须确认 | 已移除手机号与令牌 | 安全会拦下工单并暂停流转 |\n| 附件 | 选填 | 截图 2 张，含提示原文 | — |\n| 影响范围 | 选填 | 单账户或整地区 | — |",{"type":25,"children":245},[246],{"text":247,"type":29},"API 延迟类问题还应附上采样窗口、分位数和样本量；具体口径可对照[地区延迟基线](https:\u002F\u002Fwww.quanqiudaili.com\u002Fblog\u002Fsaas-api-region-latency-baseline)填写。",{"type":25,"children":249},[250],{"text":251,"type":29},"可直接复制的工单块（尖括号为占位，按团队必填项删减）：",{"type":25,"children":253},[254],{"text":255,"type":29},"标题：\u003C地区> + \u003C功能入口> + \u003C现象> + \u003C版本>\n环境\u002F版本：产品 \u003Cx.y.z>；客户端 \u003C平台与版本>；测试地区 \u003C地区>；入口 \u003C页面或 URL>\n时间与时区：\u003CYYYY-MM-DD HH:MM（UTC±x）>；首次出现 \u003C时间>；最近一次 \u003C时间>\n前置状态：\u003C账户状态、权限、功能开关、缓存状态>\n测试步骤：1) \u003C步骤> 2) \u003C步骤> 3) \u003C步骤>\n期望：\u003C应有的结果>\n实际：\u003C实际结果与提示原文>\n次数与窗口：尝试 \u003Cn 或未知> 次，复现 \u003Cm 或未知> 次，观察 \u003C窗口>；总次数未知时注明“总尝试次数未知”\n请求 ID（Trace ID）：\u003C值>；服务端返回码：\u003Ccode>\n证据脱敏确认：已移除手机号、邮箱、令牌、Cookie 与精确地址\n影响范围：\u003C单账户、单地区或多地区>\n待确认项：\u003C怀疑方向，待验证>",{"type":31,"level":21,"children":257},[258],{"text":259,"type":29},"时间戳同时记录日期、时间和 UTC 偏移",{"type":25,"children":261},[262],{"text":263,"type":29},"\"昨天下午\"这类描述无法与日志对齐。统一写成本地时间加 UTC 偏移，例如 14:05（UTC+8），并保留原始时区，方便不同团队对齐请求记录。出口或网络信息只在与问题相关时填写，并注明采集方式和时间。",{"type":31,"level":32,"children":265},[266],{"text":267,"type":29},"缺项会被退回到哪一步",{"type":25,"children":269},[270],{"text":271,"type":29},"缺项后果已并入字段表的最后一列：按团队已确认的必填条件补齐字段；没有 Trace ID 时，可提供带时区的精确请求时间、入口及其他可关联信息，并说明暂时无法取得请求标识。观察项可记录已知次数，并注明“总尝试次数未知”。涉及敏感信息时，按组织安全流程处理。",{"type":31,"level":32,"children":273},[274],{"text":275,"type":29},"提交前核对工单信息",{"type":25,"children":277},[278],{"text":279,"type":29},"提交前检查复现步骤是否可独立执行、期望与实际是否分开描述、时间是否带时区、请求标识能否关联日志，以及附件是否已脱敏。分诊不确定时写“待确认”，不要为了填字段而猜根因；若发现敏感信息，按组织安全流程暂停流转并清理附件。",{"type":31,"level":21,"children":281},[282],{"text":283,"type":29},"偶发问题注明尝试次数和观察时间范围",{"type":25,"children":285},[286],{"text":287,"type":29},"“偶发”不足以复现。记录已知的尝试次数、复现次数和观察窗口；暂时无法统计总次数时，写明采样条件、已观察到的次数，并注明“总尝试次数未知”，避免把有限观察当成稳定结论。",{"type":31,"level":32,"children":289},[290],{"text":148,"type":29},{"type":31,"level":21,"children":292},[293],{"text":294,"type":29},"没有 Trace ID，还能提交工单吗？",{"type":25,"children":296},[297],{"text":298,"type":29},"可以。有 Trace ID 时填写；没有时，提供带时区的精确请求时间、入口、复现步骤及环境，并说明暂时无法取得请求标识。是否必填或退回按团队已确认的流程处理。",{"type":31,"level":21,"children":300},[301],{"text":302,"type":29},"暂时无法稳定复现，要不要提交？",{"type":25,"children":304},[305],{"text":306,"type":29},"可以先作为观察项提交，附已知次数、尝试次数和时间范围，后续复现时补充证据。",{"type":31,"level":21,"children":308},[309],{"text":310,"type":29},"用户截图带地区信息怎么脱敏？",{"type":25,"children":312},[313],{"text":314,"type":29},"遮挡手机号、邮箱、令牌和精确地址；保留判断问题所需的地区、语言和提示信息。",{"type":31,"level":21,"children":316},[317],{"text":318,"type":29},"日志和截图可以直接附原始文件吗？",{"type":25,"children":320},[321],{"text":322,"type":29},"先检查并移除令牌、Cookie、个人信息和精确地址，再附最小必要片段。",{"source":6,"id":324,"documentId":325,"translationKey":325,"locale":9,"slug":326,"path":327,"_path":327,"title":328,"description":329,"excerpt":330,"image":331,"publishedAt":332,"updatedAt":333,"author":17,"tags":334,"featured":19,"sortOrder":20,"readingTime":32,"bodyType":22,"bodyBlocks":335,"bodyHtml":193},3655,"gpj6mdt5zocfmuao4ii43m60","saas-api-region-latency-baseline","\u002Fblog\u002Fsaas-api-region-latency-baseline","SaaS API 地区延迟基线怎么建？请求口径与分位数","SaaS API 地区延迟基线应固定接口、请求内容、客户端和采样窗口，按地区记录 p50、p95、样本量、错误率及限流情况，并说明统计口径。","SaaS API 地区延迟基线应固定接口、请求内容、客户端和采样窗口，按地区记录 p50、p95、样本量、错误率及限流情况，并说明统计口径。\n","https:\u002F\u002Fcms.quanqiudaili.com\u002Fuploads\u002Flarge_saas_api_cover_5939424cfc.webp","2026-10-26T09:51:21.825Z","2026-10-26T09:51:21.802Z",[],[336,340,344,348,352,356,360,364,368,372,376,380,384,388,392,396,400,404,408,411,415,419,423,427,431,435,439],{"type":25,"children":337},[338],{"text":339,"type":29},"报告分位数并保留样本量：p50 描述中位响应，p95 反映较慢请求，p99 仅在样本足够时参考。可比性取决于接口、客户端、负载和采样窗口一致，不存在适用于所有接口的固定请求数。本文测的是自有 API 的应用响应，不是代理网络本身的延迟与稳定性。",{"type":31,"level":32,"children":341},[342],{"text":343,"type":29},"先定分位数和判读口径",{"type":25,"children":345},[346],{"text":347,"type":29},"一个接口的平均响应时间可能掩盖尾部慢请求，因此基线通常还要报告分位数。p50 表示中位响应，p95 和 p99 描述分布尾部；同时应提供样本量、窗口、错误率和计算方法，避免只凭几个数字下结论。",{"type":73,"children":349},[350],{"text":351,"type":29},"| 指标 | 看什么 | 记录值 | 判读方式 |\n|---|---|---|---|\n| p50 | 中位响应 | 填写本轮实测值 | 按预先定义的偏差阈值复核 |\n| p95 | 较慢请求分位 | 填写本轮实测值 | 结合样本量和基线阈值复核 |\n| p99 | 尾部请求分位 | 样本足够时填写 | 结合样本量与超时策略判断 |\n| 错误率 | 按约定口径统计失败请求 | 填写本轮实测值 | 分别记录 HTTP 错误和无响应超时；分母包含约定的全部有效尝试或逻辑请求，网络失败不能因没有状态码而遗漏 |",{"type":25,"children":353},[354],{"text":355,"type":29},"示例：若 p50 稳定而 p95 明显升高、错误率变化不大，可先检查慢请求是否集中在特定时段、请求类型或下游依赖，再结合重试和连接复用记录判断。",{"type":31,"level":21,"children":357},[358],{"text":359,"type":29},"跨窗口比较时不要直接平均分位数",{"type":25,"children":361},[362],{"text":363,"type":29},"不能直接平均各窗口的分位数。总体分位数需要原始样本，或同一口径、兼容且可合并的分布数据，例如直方图或相应摘要；只有各窗口的 p95 时，不能重算总体 p95。固定窗口可用于逐窗比较，但不能恢复已经丢失的分布。使用分桶时应注明算法与精度。保留原始请求耗时是可行方案之一，并非唯一方案。",{"type":25,"children":365},[366],{"text":367,"type":29},"稳定与否要看窗口之间的波动，不看单窗口的数字。每窗口记录样本量、p95 与错误率；连续几个窗口的 p95 偏差落在预设范围内、样本量达到目标，才可宣称基线稳定，否则标为暂定并在结论中写明适用窗口。",{"type":31,"level":32,"children":369},[370],{"text":371,"type":29},"先明确延迟基线测量了哪些环节",{"type":25,"children":373},[374],{"text":375,"type":29},"基线要回答的是“用户在这个地区调用我的接口，多久能看到响应”。采样前固定测量单位和起止点：明确统计首字节（TTFB）还是完整响应体，并说明是否包含 DNS、建连、TLS、连接复用和客户端等待。它反映应用、客户端和测试网络共同作用下的观测结果；若要判断具体阶段，应在相应观测点分别采集，不能随意相加或相减来认定纯网络耗时。",{"type":31,"level":21,"children":377},[378],{"text":379,"type":29},"固定影响可比性的条件",{"type":25,"children":381},[382],{"text":383,"type":29},"固定请求体或明确区分请求类型与请求大小（含上传\u002F下载体积），记录测量起止点、是否含 DNS\u002F建连\u002FTLS、连接复用、客户端等待、采样时段、并发、客户端版本和缓存状态；不同地区使用可比的测试端与请求路径，避免把负载差异当成地区差异。",{"type":31,"level":21,"children":385},[386],{"text":387,"type":29},"分开记录预热请求与缓存命中结果",{"type":25,"children":389},[390],{"text":391,"type":29},"预热请求应单独标记，不要不加说明地混入稳态样本或直接剔除。记录剔除规则和数量；带缓存的接口还要区分命中与未命中，避免不同请求路径混在一起。测量应用响应时，应分别记录服务端处理、客户端和网络耗时。",{"type":31,"level":32,"children":393},[394],{"text":395,"type":29},"按统一口径建立并复核基线",{"type":25,"children":397},[398],{"text":399,"type":29},"1. 定接口与请求内容，记录请求体或参数，并确保测试不会修改真实用户数据。产出：接口与请求说明。\n2. 定测试地区与发起端，尽量保持客户端、版本和负载可比。产出：地区与客户端清单。\n3. 按目标分位数和流量波动确定采样量，记录预热请求及剔除理由。产出：可复核的原始样本。\n4. 按固定算法计算 p50、p95、适用时的 p99、错误率与限流占比。产出：一期统计结果。\n5. 在可比窗口复测，并根据业务周期评估基线稳定性。产出：注明适用范围和限制的基线。若这套基线用于地区发布观测，可将窗口和分组口径接入[地区灰度验证](https:\u002F\u002Fwww.quanqiudaili.com\u002Fblog\u002Fsaas-regional-canary-release-rollback-criteria)，但仍需单独定义发布动作和回滚条件。",{"type":31,"level":21,"children":401},[402],{"text":403,"type":29},"对照服务端、客户端和网络指标分析波动",{"type":25,"children":405},[406],{"text":407,"type":29},"延迟波动可能来自服务端排队、网络、客户端负载、缓存或重试。按一次请求尝试还是含重试的逻辑请求统计应预先定义；成功耗时、HTTP 错误和无响应超时分别记录。先按地区和版本拆分数据，再结合服务端监控、客户端日志和请求标识归因；地区差异不能直接等同于网络或代理差异。",{"type":31,"level":32,"children":409},[410],{"text":148,"type":29},{"type":31,"level":21,"children":412},[413],{"text":414,"type":29},"每地区多少样本才够报 p95？",{"type":25,"children":416},[417],{"text":418,"type":29},"没有通用固定值。样本不足以稳定估计 p95 时，应继续采样或把结果标为暂定。",{"type":31,"level":21,"children":420},[421],{"text":422,"type":29},"预热请求要不要计入稳态基线？",{"type":25,"children":424},[425],{"text":426,"type":29},"先按目标区分冷启动和稳态结果；若剔除预热请求，注明规则和剔除数量。",{"type":31,"level":21,"children":428},[429],{"text":430,"type":29},"被限流的请求要不要计入延迟？",{"type":25,"children":432},[433],{"text":434,"type":29},"将 429 与成功请求分开统计，并同时报告限流数量和占比。",{"type":31,"level":21,"children":436},[437],{"text":438,"type":29},"不同地区的 p95 可以直接取平均吗？",{"type":25,"children":440},[441],{"text":442,"type":29},"不建议。总体分位数需基于原始样本或兼容、可合并的分布数据重新计算；仅有各地区的 p95 无法还原总体 p95。若使用固定窗口，只能按窗口比较。",{"source":6,"id":444,"documentId":445,"translationKey":445,"locale":9,"slug":446,"path":447,"_path":447,"title":448,"description":449,"excerpt":450,"image":451,"publishedAt":452,"updatedAt":453,"author":17,"tags":454,"featured":19,"sortOrder":20,"readingTime":32,"bodyType":22,"bodyBlocks":455,"bodyHtml":193},3654,"ls62ptetizm1ge4vnl0di4nr","saas-mfa-region-compatibility-recovery-testing","\u002Fblog\u002Fsaas-mfa-region-compatibility-recovery-testing","SaaS MFA 地区兼容测试怎么做？失败排查与账户恢复","用授权测试账户按挑战类型检查地区兼容性，记录设备时间偏差、验证码通道、锁定提示与恢复结果，并结合产品策略和审计日志定位差异。","用授权测试账户按挑战类型检查地区兼容性，记录设备时间偏差、验证码通道、锁定提示与恢复结果，并结合产品策略和审计日志定位差异。\n","https:\u002F\u002Fcms.quanqiudaili.com\u002Fuploads\u002Flarge_saas_mfa_cover_0fc7feefdf.webp","2026-10-26T09:51:15.193Z","2026-10-26T09:51:15.180Z",[],[456,460,464,468,472,476,480,484,488,492,496,500,504,508,512,516,520,524,528,531,535,539,543,547,551,555,559],{"type":25,"children":457},[458],{"text":459,"type":29},"先按挑战类型核对时间、通道和账户状态，再结合服务端记录确认是否命中地区策略。本文围绕授权测试账户，验证挑战、提示、恢复与日志，不提供绕过 MFA 的方法。",{"type":31,"level":32,"children":461},[462],{"text":463,"type":29},"按现象区分时间、通道和账户问题",{"type":25,"children":465},[466],{"text":467,"type":29},"收到验证码却无法通过时，时间偏差是需要核对的条件之一；容错窗口取决于产品实现。测试前记录客户端与服务端时间差，并按产品规格覆盖窗口内外的用例。若验证码未送达，则先查发送回执和设备状态。",{"type":73,"children":469},[470],{"text":471,"type":29},"| 现象 | 更可能是 | 先做哪一步 | 判为地区问题的条件 |\n|---|---|---|---|\n| TOTP 验证失败 | 生成端与验证端时间、步长或容错窗口 | 记录两端 Unix 时间及产品配置，按窗口内外用例核验 | 需结合服务端命中的地区策略证据，不能仅凭校时后仍失败判定 |\n| 短信或邮件验证码未通过 | 生成、投递、提交时间或服务端有效期 | 记录各阶段时间、回执和挑战结果 | 需结合服务端命中的地区策略证据；原地区成功仅是线索 |\n| 推送挑战未完成 | 设备令牌、推送通道或账户状态 | 查设备令牌状态、通道结果和服务端事件 | 按产品规格和实际命中的地区策略证据判断 |\n| 连续失败后被锁 | 失败计数策略 | 按产品规定核对锁定对象和恢复路径 | 结合锁定状态、挑战类型及策略记录判断 |\n| 未收到挑战码 | 发送、投递或设备接收异常 | 查发送回执、重试记录与设备状态 | 按产品规定的通道结果和日志判断 |",{"type":25,"children":473},[474],{"text":475,"type":29},"示例：测试机与服务端存在明显时间偏差时，同一验证码可能在提交前失效。记录偏差值、挑战类型和服务端结果，校准后按相同条件复测。",{"type":31,"level":21,"children":477},[478],{"text":479,"type":29},"按产品的验证码有效窗口核对时间偏差",{"type":25,"children":481},[482],{"text":483,"type":29},"不必追求毫秒级测量，但要记录偏差方向和数值，并与产品配置的验证码有效窗口比较。自动对时或设备休眠恢复可能造成实际时钟偏差；仅改显示时区通常不会改变 Unix 时间。TOTP 应按生成端和验证端 Unix 时间、时间步长及容错窗口核验。短信\u002F邮件码应按生成、投递、提交时间和服务端有效期判断；推送挑战应检查设备令牌与通道状态。",{"type":31,"level":32,"children":485},[486],{"text":487,"type":29},"地区差异从验证码通道和额外验证策略排查",{"type":25,"children":489},[490],{"text":491,"type":29},"MFA 结果可能受时间、挑战类型、账户状态、通道和服务端策略共同影响。地区差异可从验证码通道可达性及产品是否配置额外验证两方面检查，再用服务端日志确认实际命中的规则。",{"type":31,"level":21,"children":493},[494],{"text":495,"type":29},"区分验证码未送达和产品要求额外验证",{"type":25,"children":497},[498],{"text":499,"type":29},"短信、邮件或推送通道可能出现延迟、拒收或设备令牌失效；地区策略也可能要求额外验证。结合发送回执、设备状态和服务端事件，确认失败发生在验证码校验、通道送达还是进入挑战之前。",{"type":31,"level":21,"children":501},[502],{"text":503,"type":29},"通过发送回执和服务端事件定位通道故障",{"type":25,"children":505},[506],{"text":507,"type":29},"先检查挑战是否生成、通道是否接受发送、设备是否收到，以及服务端记录的失败阶段。测试时分别记录地区配置、客户端时区与网络条件；只在产品测试方案要求时才改变网络条件。",{"type":31,"level":32,"children":509},[510],{"text":511,"type":29},"在测试账户上验证挑战、锁定和恢复流程",{"type":25,"children":513},[514],{"text":515,"type":29},"先在对照地区验证账户和挑战通道，再按测试计划逐个改变地区条件并记录服务端实际命中的策略。诊断账户按批准的失败预算测试，必须在触及锁定阈值前停止；不要用这些诊断结果声称已验证锁定。",{"type":25,"children":517},[518],{"text":519,"type":29},"锁定验收应使用专用测试账户，在隔离环境中按批准计划触发产品阈值，再核对锁定提示、恢复方式和审计记录。不要在生产账户或未授权账户上反复试码。验证码、恢复码和一次性口令不写入记录或截图，工单只写脱敏后的测试编号。",{"type":31,"level":21,"children":521},[522],{"text":523,"type":29},"恢复路径要在失败前演练",{"type":25,"children":525},[526],{"text":527,"type":29},"锁定验收应在专用测试账户和隔离环境中按批准计划触发产品阈值，核对锁定对象（账户、认证器或通道）、解锁条件、恢复码及备用方式是否可用。按产品规格检查恢复码一次消费、旧码或重新生成后的码是否失效、恢复后的会话状态及审计事件。恢复后还需检查登录状态、续期与退出，可参照[浏览器会话地区回归](https:\u002F\u002Fwww.quanqiudaili.com\u002Fblog\u002Fsaas-session-state-preference-cross-region-regression)。",{"type":31,"level":32,"children":529},[530],{"text":148,"type":29},{"type":31,"level":21,"children":532},[533],{"text":534,"type":29},"改了设备时区，就等于改变验证码时间吗？",{"type":25,"children":536},[537],{"text":538,"type":29},"不一定。时区显示与系统时钟是不同设置，需记录设备实际时间相对服务端的偏差。",{"type":31,"level":21,"children":540},[541],{"text":542,"type":29},"连续失败被锁，恢复走哪条路径？",{"type":25,"children":544},[545],{"text":546,"type":29},"按产品规格确认锁定对象和解锁条件，再使用可用的恢复码、备用验证方式或管理员支持。核对恢复码的消费与失效规则、恢复后的会话和审计记录；不要把解锁后仍失败直接归为地区问题。",{"type":31,"level":21,"children":548},[549],{"text":550,"type":29},"如何区分通道未送达和验证码校验失败？",{"type":25,"children":552},[553],{"text":554,"type":29},"看服务端事件停在哪一步：挑战是否生成、通道是否返回受理、设备是否上报接收，最后才是校验结果。日志里要有挑战 ID、通道回执状态和时间戳；只有校验环节报错，才算验证码本身失败。",{"type":31,"level":21,"children":556},[557],{"text":558,"type":29},"测试能要求临时关闭 MFA 吗，边界在哪？",{"type":25,"children":560},[561],{"text":562,"type":29},"不要为通过测试而绕过 MFA。使用专用授权账户验证完整挑战和恢复流程。",[564],{"source":6,"id":7,"documentId":8,"translationKey":8,"locale":9,"slug":10,"path":11,"_path":11,"title":12,"description":13,"excerpt":13,"image":14,"publishedAt":15,"updatedAt":16,"author":17,"tags":565,"featured":19,"sortOrder":20,"readingTime":21,"bodyType":22,"bodyBlocks":566,"bodyHtml":193},[],[567,570,573,576,579,582,585,588,591,594,597,600,603,606,609,612,615,618,621,624,627,630,633,636,639,642,645,648,651,654,657,660,663,666,669,672,675,678,681,684,687],{"type":25,"children":568},[569],{"text":28,"type":29},{"type":31,"level":32,"children":571},[572],{"text":35,"type":29},{"type":25,"children":574},[575],{"text":39,"type":29},{"type":25,"children":577},[578],{"text":43,"type":29},{"type":25,"children":580},[581],{"text":47,"type":29},{"type":25,"children":583},[584],{"text":51,"type":29},{"type":25,"children":586},[587],{"text":55,"type":29},{"type":31,"level":32,"children":589},[590],{"text":59,"type":29},{"type":25,"children":592},[593],{"text":63,"type":29},{"type":31,"level":21,"children":595},[596],{"text":67,"type":29},{"type":25,"children":598},[599],{"text":71,"type":29},{"type":73,"children":601},[602],{"text":76,"type":29},{"type":25,"children":604},[605],{"text":80,"type":29},{"type":25,"children":607},[608],{"text":84,"type":29},{"type":31,"level":21,"children":610},[611],{"text":88,"type":29},{"type":25,"children":613},[614],{"text":92,"type":29},{"type":25,"children":616},[617],{"text":96,"type":29},{"type":31,"level":32,"children":619},[620],{"text":100,"type":29},{"type":25,"children":622},[623],{"text":104,"type":29},{"type":25,"children":625},[626],{"text":108,"type":29},{"type":25,"children":628},[629],{"text":112,"type":29},{"type":25,"children":631},[632],{"text":116,"type":29},{"type":31,"level":32,"children":634},[635],{"text":120,"type":29},{"type":25,"children":637},[638],{"text":124,"type":29},{"type":25,"children":640},[641],{"text":128,"type":29},{"type":25,"children":643},[644],{"text":132,"type":29},{"type":25,"children":646},[647],{"text":136,"type":29},{"type":25,"children":649},[650],{"text":140,"type":29},{"type":25,"children":652},[653],{"text":144,"type":29},{"type":31,"level":32,"children":655},[656],{"text":148,"type":29},{"type":31,"level":21,"children":658},[659],{"text":152,"type":29},{"type":25,"children":661},[662],{"text":156,"type":29},{"type":31,"level":21,"children":664},[665],{"text":160,"type":29},{"type":25,"children":667},[668],{"text":164,"type":29},{"type":31,"level":21,"children":670},[671],{"text":168,"type":29},{"type":25,"children":673},[674],{"text":172,"type":29},{"type":31,"level":21,"children":676},[677],{"text":176,"type":29},{"type":25,"children":679},[680],{"text":180,"type":29},{"type":25,"children":682},[683],{"text":184,"type":29},{"type":25,"children":685},[686],{"text":188,"type":29},{"type":25,"children":688},[689],{"text":192,"type":29},null,[],[]]