架构与系统设计 面试题库
收录真实面试常见问题,答案长度适合口头表达;拿不准时可返回相关主题复习。
设计原则
14个问题 · 0 已看01 哪些决定值得写成架构决策记录? 查看答案 ▾ 收起 ▴
当一个决定会实质影响系统结构、质量属性、依赖或接口边界,或者改变多个团队的协作方式时,应写 ADR。回退成本高、存在多个可信选项,也是很强的信号。不要记录每个实现细节:局部命名属于代码审查,临时运维变通属于工单或运行手册。实用的判断标准是,未来维护者是否需要知道当时的背景、备选方案与取舍,才能安全地修改系统。应在证据仍然完整时记录决定。
02 怎样把模糊的质量目标改写为架构场景? 查看答案 ▾ 收起 ▴
把“可扩展”或“有韧性”这样的形容词换成刺激和可观察响应,并写出来源、事件、运行环境、受影响对象、预期行为与度量方式。例如支付超时时,可以要求两秒内返回可查询的处理中状态,并复用同一个幂等键,而不是泛泛声称系统高可用。性能目标还必须说明负载、数据规模、环境和百分位口径。这样的场景既约束设计选择,也明确该测试什么,不会把尚未测量的质量当成既成事实。
03 为什么方法签名与基类型一致,仍不足以满足 LSP? 查看答案 ▾ 收起 ▴
签名只描述形状,不包含调用者依赖的全部行为。一个替代实现可以通过编译,却拒绝基础契约接受的输入、返回承诺范围之外的值、破坏状态不变量,或在产生副作用后引入新的失败。这些变化加强了前置条件或削弱了后置条件,迫使调用者增加子类型专用分支。应通过基础接口编写一套共享契约测试,覆盖边界输入、状态转换、结果与失败,并对每个实现运行。实现专属测试可以补充细节,却不能取代共同证据。
04 不依赖单一健康分数时,怎样排列技术债务的优先级? 查看答案 ▾ 收起 ▴
先处理不可接受的安全、数据丢失、合规风险或正在发生的事故。其余项目并列比较近期变化频率、每次变化观察到的额外工作、影响半径、修复范围与不确定性,并链接证据。这样会暴露假设,而不是用任意权重掩盖它们。静态分析结果和覆盖率只是调查信号,本身不代表业务价值。处理结果可以是立即偿还、结合下一项相关功能修复、设置事件触发条件后接受,或作为误报关闭。还要记录为什么该选择胜过机会成本,以及什么证据能证明项目已完成。
05 整洁架构中的依赖规则保护什么? 查看答案 ▾ 收起 ▴
这条规则保护业务策略,使其不必知道交付与基础设施细节。源码依赖指向内层:用例可以定义自己需要的仓储或展示契约,数据库或 HTTP 适配器实现该契约。运行时调用可以双向跨越边界;规则关注的是哪个模块在命名和导入另一个模块。跨边界数据应使用应用自己拥有的结构,而不是 ORM 行或框架请求对象。一个实用检查是,核心能否用简单替身测试,并且无需导入 Web 框架、数据库驱动或消息代理就能修改。
06 怎样说明整洁架构、洋葱架构与六边形架构的差异,同时保留它们的共同规则? 查看答案 ▾ 收起 ▴
三者都通过依赖倒置,让应用或领域策略独立于可替换的基础设施。整洁架构强调同心的策略层级与用例;洋葱架构强调由应用层和基础设施层包围的领域模型;六边形架构则描述由适配器实现的入站端口与出站端口。图形和术语的差异大于目标差异。不要强行把每个圆环与端口逐一对应,而应找出核心策略、明确它拥有的契约、把适配器放在外部,并在真实代码中验证导入方向和边界数据。
39 已接受 ADR 的背景或决策过时后,应如何处理? 查看答案 ▾ 收起 ▴
在 Node 24 基线上,已接受 ADR 是历史记录,不是可随意改写的当前架构说明。应新建 ADR,说明已变化的背景,比较可行选项,并写出替代决策。把旧记录标记为已取代,在两份记录中双向链接;不能复用旧 ID,也不能重写旧理由以迎合当前代码。小型编辑修正只能在含义不变时作为带日期补充。这会增加记录数量,但可查询索引能保留旧 commit 存在的原因,并防止稳定链接悄然指向另一个决策。
40 如何让 ADR 在决策实施后仍然可验证? 查看答案 ▾ 收起 ▴
在 Node 24 系统中,应把每个重要的预期后果连接到证据:用架构测试检查 import 方向,用契约测试检查兼容性,用 telemetry 观察延迟,用恢复演练验证韧性。还要记录负责角色、观测时机,以及流量、法规或恢复目标变化等复审触发条件。“已接受”表示决策生效,不表示交付完成或收益已证明。要避免“更可扩展”这类无法发现漂移的模糊后果。额外维护成本只对重大假设值得,因此验证应保持聚焦,替代 ADR 改变契约后还应退役过时检查。
41 如何选择合适的架构视图,避免混合抽象层级? 查看答案 ▾ 收起 ▴
对 Node 24 应用,应先确定决策问题和受众。用 context 视图表示用户、外部系统和信任边界;用 container 视图表示可部署单元、协议与存储;用 component 视图表示一个 container 内的责任与依赖方向。视图应写明范围、日期和省略规则,并给每条重要关系标注方向与用途。把类、云资源和外部角色混在一张图中,会让边界淹没于细节。图不等于约束;重要连线应由 import 规则、权限或契约测试支撑,并随系统变化用部署证据校对视图。
42 如何让架构持续演进,又不为每个想象中的未来过度设计? 查看答案 ▾ 收起 ▴
以 Node 24 为基线,先为当前质量场景和硬约束排序,将现状与可行替代方案比较,再选择满足它们的最简单结构。不确定的增长应标为假设,不要预先安装队列、服务或副本。随后建立反馈环:自动依赖检查保护稳定边界,telemetry 暴露运行时压力,ADR 复审触发条件在证据变化时重开决策。陷阱是同时最优化所有质量属性;每个机制都会增加运维与故障成本。可逆选择应保持局部,用原型验证风险最高的不可逆假设,并记录哪些证据才足以支持下一步结构变化。
43 如何应用 SRP 与 OCP,而不是为每个方法创建一个类? 查看答案 ▾ 收起 ▴
在 TypeScript 6 中,这两项原则都不要求必须使用类。应用 SRP 时,要按发起变更的角色、共同不变量,以及真实或已承诺工作中的共变证据组织行为;方法数量无关紧要。应用 OCP 时,只在独立变体已经出现或已排期的地方增加函数、模块或接口边界,并定义可观察契约。稳定的局部计算直接保留更清楚。机械拆分会增加导航、注入和 test double 成本,而耦合仍存在于多个文件之间。应用真实的第二种实现与变更场景验证边界;若每次变更仍同时修改同一组模块,该抽象并未隔离变化原因。
44 为什么使用依赖注入容器本身不能证明满足 DIP? 查看答案 ▾ 收起 ▴
在 TypeScript 6 中,容器可以隐藏具体构造,但高层业务模块仍可能导入供应商类型或 service locator token。DIP 关心的是源码依赖方向与契约所有权:高层策略用自身业务语言定义 port,外部 adapter 实现它,只有 composition root 可以同时了解两者。类型检查只能证明形状。还要用契约测试验证合法输入、输出、状态变化与失败,并用 import 规则阻止策略反向访问 adapter。这种边界需要额外维护,因此只应用于技术替换、测试隔离或独立变更真实存在的地方,而不是包装每个稳定 helper。
45 如何区分技术债务、缺陷、功能需求与代码气味? 查看答案 ▾ 收起 ▴
对 Node 24 系统,只有某项设计或构造选择会给一类具体未来变更增加额外成本或风险时,才称为技术债务。当前行为错误是缺陷,缺少业务能力是产品工作,代码气味或覆盖率数字在连接到影响之前只是信号。记录应包含受影响的变更、延误或事故等已观测利息、本金、目标状态、owner 和退出证据。这种分类能防止债务清单变成无法排序的杂物箱。代价是调查时间,因此当代码稳定、已计划删除,或没有未来变更成本证据时,应关闭误报。
46 如何逐步偿还技术债务,又不创造另一个永久迁移层? 查看答案 ▾ 收起 ▴
在 Node 24 代码库中,先用特征测试和相关 telemetry 保护可观察行为。在经常变更的边界建立接缝,移动一个边界清楚的切片,比较结果,并保留经测试的回滚路径。每个临时 adapter、feature flag 或双读路径都需要 owner 和删除条件。只有目标结构已存在、外部行为仍有效,且退出证据表明旧路径已不可达时,才能关闭债务项。全量重写看起来更干净,却会丢弃隐藏行为并让回滚粗糙;只有无法建立增量接缝,且迁移、对账与恢复均可独立验证时,才应选择它。
设计模式
6个问题 · 0 已看07 怎样判断一个设计模式是否应该进入解决方案? 查看答案 ▾ 收起 ▴
先说明反复出现的设计压力,而不是先报模式名称。要讲清什么会变化、什么必须稳定、谁拥有变化,以及更简单的设计为什么已经失败或成本过高。再比较模式新增的间接层、状态、对象分配和调试成本,与它消除的耦合。例如,多个可替换策略确实独立变化时,Strategy 才有价值;只有两个稳定分支时,一个条件判断可能更清楚。最后用一个小型变更场景和测试验证选择。模式是描述取舍的共同词汇,不是照抄教科书类图的要求。
08 Strategy 模式与 State 模式在实践中有什么区别? 查看答案 ▾ 收起 ▴
Strategy 为一项工作选择可替换算法,通常由客户端或组合根决定;切换算法本身不表示生命周期。State 则建模对象随当前状态变化的行为,状态转换属于对象规则。两者都可能通过共同接口委托,因此类图看起来很像。判断时要问:谁选择实现,转换是否属于领域行为。在多种定价算法之间选择更像 Strategy;订单从待支付变为已支付或已取消更像 State,尤其是每次转换都必须限制允许执行的操作时。
09 什么条件让模块化单体真正具备模块性? 查看答案 ▾ 收起 ▴
模块必须有明确所有权、公开入口和普通代码无法绕过的数据边界。单一部署单元不等于单一且不可分割的模型。调用应经过模块门面或已发布事件,同时禁止直接导入内部实现和跨模块访问数据表。可以用包可见性、导入检查、架构测试,以及适用时的模式权限来执行规则。共享内核应保持很小,并由相关团队共同审查。关键检验是,一个模块能否独立演进或日后被提取,而无需在整个仓库中寻找隐藏调用与共享写入。
10 舱壁模式要限制哪类故障,又必须隔离什么? 查看答案 ▾ 收起 ▴
舱壁模式防止一个依赖或一类工作耗尽全部共享资源,进而拖垮无关业务。隔离必须对应真正稀缺的资源,例如独立连接池、线程或工作进程池、队列、并发上限,有时还包括进程或单元边界。仅把调用放进不同类没有作用。应根据实测需求确定容量,为关键路径预留资源,定义溢出行为,并观测饱和与拒绝。隔离会缩小影响半径,但也可能浪费容量或把竞争下移。例如两个工作池若仍共用并耗尽同一数据库连接池,隔离就没有完成。
11 怎样用绞杀者模式安全迁移一项能力? 查看答案 ▾ 收起 ▴
先在遗留能力前建立路由接缝,选择边界清楚的小切片,并在迁移流量前定义功能对等与回退证据。写入必须有一个权威路径;不受控的双写会产生部分成功和顺序错误。若两种模型都需要数据,应通过 outbox、变更数据捕获或可对账的迁移流程传播变化。比较影子读取或业务结果,再逐步切换流量,并观察错误、延迟与数据偏差。回退方案必须处理新路径已接受的写入。只有对账证明切换完成后,才能删除旧路由、同步代码和临时开关。
12 怎样避免功能开关变成永久复杂度? 查看答案 ▾ 收起 ▴
每个开关都应有类型、负责人、创建日期、发布或实验指标、安全默认值与删除条件。评估应靠近有意设计的边界,并在单次请求中根据已捕获的开关值保持行为确定。两个分支并存时都要测试,包括开关服务失败的情况,但不要让每项测试乘上所有无关开关组合。发布完成后,应按计划同时删除落败分支、配置、遥测和测试。清单检查可以提醒过期开关。长期保留的紧急开关也仍需演练、访问控制与定期审查。
系统设计
6个问题 · 0 已看13 系统设计面试的第一轮分析应该怎样展开? 查看答案 ▾ 收起 ▴
先澄清用户、核心操作、正确性规则和明确排除的范围。把质量目标改写为可度量的负载、延迟、可用性、持久性与新鲜度要求,再只估算那些会改变设计的数字。画出请求路径和数据路径,分配状态所有权,并找出第一个可能的瓶颈或故障边界。先讨论一个基线,再增加缓存、队列、副本或分片。每增加一项,都要说明它缓解了什么压力,又引入了什么失败。最后回到需求,指出哪些假设要用生产证据验证。
14 哪些职责应该放进 API 网关,哪些不应该? 查看答案 ▾ 收起 ▴
网关应负责跨服务一致的边缘关注点,例如路由、TLS 终止、身份验证执行、粗粒度限流、协议适配、请求关联,有时还包括面向特定客户端的聚合。领域授权、业务校验和数据不变量仍由拥有该领域的服务负责,因为只有它掌握必要状态与语义。转换规则要明确并带版本,避免网关变成隐藏的第二套应用。对于支付请求,网关可以验证令牌与配额,但是否允许该客户从该账户扣款、状态转换是否合法,必须由支付服务决定。
15 怎样设计 API 组合,避免放大延迟与故障? 查看答案 ▾ 收起 ▴
先定义组合响应契约,区分必需数据与可选补充信息。独立调用应在同一个端到端截止时间内并发执行,传播取消,并为每个依赖分配更小预算。限制扇出,通过批量 API 或专用读取模型避免 N+1 调用。要逐字段决定:依赖失败时是让整个响应失败、返回明确的不可用状态,还是使用有新鲜度上限的缓存;绝不能把陈旧数据悄悄伪装成当前数据。应度量关键路径、部分结果比例与下游负载。重试必须留在同一截止时间内,并且只用于安全的瞬时失败操作。
16 怎样让后台任务可以安全重试? 查看答案 ▾ 收起 ▴
要假设工作进程可能在产生效果后、确认消息前停止,因此任务会再次运行。为逻辑操作提供稳定标识,尽可能把完成记录与自有状态原子写入,并让外部效果具备幂等或去重能力。只有持久完成后才确认消息。失败要分类:瞬时失败使用有上限的指数退避与抖动重试,永久失败或重试耗尽则进入可见的死信流程,并保留足够修复上下文。超时、取消、并发限制和可观测性也属于契约。业务效果的“恰好一次”来自设计,而不是队列标签。
17 无状态请求处理为什么有利于水平扩展,系统中又仍有哪些状态? 查看答案 ▾ 收起 ▴
如果任意健康实例都能处理下一个请求,负载均衡器就可以增加、移除或替换实例,而无需维持会话粘性。这样会简化扩缩容与恢复,但不等于系统没有状态。会话、幂等记录、限流计数、缓存、工作流和业务数据仍然存在,都需要明确所有权、一致性、容量与故障策略。持久状态应放入合适的存储,本地只保留可丢弃缓存。对于上传或长流程,应使用稳定操作 ID,让另一实例从共享进度继续,而不是依赖某个进程的内存。
18 什么时候独立部署足以证明服务边界或微前端边界合理? 查看答案 ▾ 收起 ▴
当一个内聚的业务能力拥有独立所有权、发布节奏、扩缩容或故障需求,并与邻近部分保持稳定契约时,独立部署才有价值。仅创建新仓库或运行时并不会自动获得这种能力。后端服务会引入网络故障、数据一致性、安全与运维成本;微前端会引入资源、路由、共享依赖、样式与浏览器集成风险。应检查该切片能否独立构建、测试、发布、观测和回退。若每次模式、共享包或页面发布仍要跨团队同步,拆分只是把耦合转移到了部署阶段。
分布式系统
9个问题 · 0 已看19 CAP 定理究竟迫使分布式系统选择什么? 查看答案 ▾ 收起 ▴
CAP 适用于保存同一份可变状态、却无法通信的副本。如果两侧都必须完成操作,其中一侧可能接受另一侧看不到的更新,操作历史便可能失去线性一致性。若要保持线性一致,至少一侧必须拒绝或无限期延迟某些原本有效的操作,从而在该侧放弃 CAP 可用性。分区容错更适合作为故障模型,而不是菜单中的一项收益。真正的设计问题是,分区期间哪项操作与不变量选择一致性,哪项选择可用性;同一产品的不同路径可以作出不同选择。
20 超时、重试与断路器应该怎样配合? 查看答案 ▾ 收起 ▴
超时限制每次尝试,调用者还需要一个覆盖全部尝试的总截止时间。只对安全可重复操作的瞬时失败进行重试,并使用退避、抖动和较小的尝试预算。断路器按某个依赖与操作类别观察结果;失败或慢调用超过阈值后,它会快速拒绝,让资源有机会恢复。打开期结束后,只允许少量半开探测。不要在每一层独立叠加重试,否则尝试次数会相乘并压垮依赖。应度量尝试、拒绝、延迟、饱和与最终结果,再根据真实故障行为调参。
21 怎样在同步与异步服务通信之间选择? 查看答案 ▾ 收起 ▴
当调用者必须立即得到答案才能继续,并且可以接受该依赖进入自身延迟与可用性路径时,使用同步通信。工作可以先接受后完成、多个消费者需要同一事实,或需要时间解耦时,可以使用消息。消息不会消除耦合,而是把耦合转移到模式、交付语义、顺序、重试与积压延迟。应先说明用户可见契约。例如结账时的价格检查可在截止时间内同步执行,发送回执则可异步处理。无论哪种方式,都要定义超时、幂等、兼容性、所有权、可观测性和失败时的用户体验。
22 工作流什么时候选择编舞,而不是编排? 查看答案 ▾ 收起 ▴
当服务只需独立响应稳定的领域事实,而且没有参与者需要掌握全局进度时,可以选择编舞。它让发布者不知道消费者,但事件链增长后,流程会更难发现、超时和修复。若顺序、截止时间、补偿、运维可见性或明确的流程状态很重要,应选择编排。编排器负责协调,不应吞并各服务的领域规则。混合方式很常见:编排器管理一个有界工作流,再向其他领域发布结果事件。选择时应比较所有权、变更耦合、故障恢复与审计需求,而不是只看事件数量。
23 为什么 Saga 补偿不等同于数据库回滚? 查看答案 ▾ 收起 ▴
Saga 的每一步都会提交本地事务,而且可能在后续步骤失败前就暴露效果。补偿是一项新的业务操作,用语义抵消较早的操作;它不会抹掉历史,也不保证恢复到完全相同的先前状态。退款不同于删除扣款,已发送邮件也无法撤回。实现前要为每个可逆步骤定义补偿、幂等、顺序、截止时间和人工修复状态。还要持久化 Saga 进度,使崩溃后能够继续恢复。有些效果不可逆,因此流程可能需要预留、延迟承诺或面向客户的明确对账,而不能假装可以回滚。
24 幂等键实现必须存储并执行哪些规则? 查看答案 ▾ 收起 ▴
幂等键要限定在调用者与操作范围内,并绑定规范化的请求指纹;相同键配不同输入必须被拒绝。系统应原子创建记录,区分处理中、已成功、可重试失败与终止失败。并发重复请求必须汇聚到这条记录,而不能执行两次。要保存重放原始结果所需的状态码与响应,同时避免不安全地存储秘密。保留期应根据客户端重试窗口和业务风险确定。该键只保护一个服务端操作;下游副作用仍需传递同一操作标识、使用 outbox,或建立自己的去重边界。
25 路由与健康信号怎样维持单元化架构的隔离? 查看答案 ▾ 收起 ▴
应使用稳定映射把租户或工作负载分配到单元,并让路由层不保存业务数据。服务发现和健康检查可以告诉路由器哪些端点符合条件,但注册表中的健康状态并不能证明请求一定成功,而且观测可能滞后。因此还需要请求截止时间、就绪判定与单元级饱和信号。不要把故障单元的全部流量自动倾倒到健康单元,否则可能耗尽后者资源并破坏影响半径边界。故障转移需要兼容数据、预留容量、明确策略,以及针对重新分配期间陈旧映射的测试。
37 为什么法定人数计算本身不能证明系统具有强一致性? 查看答案 ▾ 收起 ▴
读写法定人数相交,可以保证一次读取至少联系到参与某次已完成写入的副本,但算术本身并没有定义哪个值获胜。协议仍需要版本或任期、并发写入裁决规则、正确的成员关系,以及拒绝过期 leader 的方法。宽松法定人数与 hinted handoff 还可能有意联系首选集合之外的副本,从而削弱简单的相交论证。应先说明一致性契约,再验证完整协议在消息延迟、重试、崩溃、重配置和分区恢复下的行为,不能只把 R + W > N 当作证明。
38 选择可用性的系统必须为网络分区后的恢复定义什么? 查看答案 ▾ 收起 ▴
如果分区两侧都接受写入,重新连接时会出现并发历史,并不会自动恢复成唯一正确值。设计必须定义冲突检测、合并语义、墓碑保留、修复所有权,以及副本收敛期间用户看到的状态。最后写入者获胜是一项策略,不是中立恢复;时钟偏差可能丢弃有效更新。有些数据可用 CRDT 合并,唯一预订等不变量则可能需要补偿或协调。测试应覆盖反复分区与重试,保留幂等标识,并监控未解决冲突,使最终收敛成为运维承诺,而不是一句口号。
领域驱动设计
6个问题 · 0 已看26 为什么限界上下文不只是服务边界? 查看答案 ▾ 收起 ▴
限界上下文定义一套模型与通用语言在什么范围内保持一致含义。它首先是语义边界,部署方式是另一项选择。同一个词在不同上下文中可以合法地表示不同概念,因此集成需要明确映射,而不是共享一个万能实体。例如 Customer 在计费中可能表示信用关系,在配送中则表示收件资料。一个上下文可以先实现为模块,一个服务也可能暂时承载多个上下文。应从语言、规则、所有权与变化模式发现边界,再根据运维需求选择进程和数据边界。
27 在 DDD 中怎样选择聚合边界? 查看答案 ▾ 收起 ▴
只把必须在一个原子事务中满足业务不变量的实体和值对象放进同一聚合,并通过聚合根暴露修改。其他聚合应按标识引用,跨聚合工作由应用逻辑、领域事件或流程管理器协调。庞大的对象图并不能证明它应该成为一个聚合;过大的聚合会产生竞争,还会迫使无关数据一起加载。例如订单行数量与订单总额可能需要同一边界,客户信用则可以属于另一边界。要在并发变化下测试命令,并明确哪些一致性是即时的,哪些是最终的。
28 什么时候领域原语比字符串或数字更合适? 查看答案 ▾ 收起 ▴
当标量带有应始终共同存在的业务含义、校验、规范化、单位或安全规则时,应使用领域原语。它应通过唯一的校验路径创建,保持不可变,并以领域语言公开操作。EmailAddress 可以阻止未校验字符串跨越边界;Money 可以要求货币类型,并禁止不同货币被意外相加。不要机械包装每个标量。只有当类型能让无效状态更难表达,或避免参数混淆时,它才有价值。解析外部输入可以返回结构化失败,而领域内部只处理已经有效的值。
29 怎样让领域事件可靠到足以供其他组件使用? 查看答案 ▾ 收起 ▴
事件名称应表示已经发生的领域事实,并包含稳定事件 ID、发生时间、聚合标识,以及消费者所需的业务数据。载荷应保持不可变,契约演进必须兼容。在聚合中提出事件不等于可靠发布;应把自有状态与 outbox 记录原子提交,再通过重试发布。消费者仍要按事件 ID 去重,并处理延迟或乱序交付。处理器不应回查生产者来获取定义该事实的数据,否则会形成时间耦合,还可能读到更新后的状态。
30 除了满墙事件,Event Storming 还应该产出什么? 查看答案 ▾ 收起 ▴
工作坊应揭示领域事实的共同时间线、触发它们的命令与参与者、作出响应的策略、外部系统、重要读取模型,以及参与者存在分歧或缺少证据的热点。热点是有价值的产出,不是要隐藏的缺陷。可以根据语言变化、策略所有权与一致性需求提出上下文和聚合边界,但这些边界只是待验证假设。会后要记录未决问题、负责人和实验。彩色便签本身不是实现设计;在把模型变成服务、模式或类之前,还要用真实场景、例外情况和领域专家进行验证。
31 CQRS 与事件溯源有什么关系,为什么它们是两个独立选择? 查看答案 ▾ 收起 ▴
CQRS 把接受命令的模型与面向查询优化的模型分开。事件溯源把已接受的状态变化保存为只追加事件历史,并通过重放重建当前状态。两者很适合组合,因为事件流可以驱动读取投影,但谁也不要求另一个存在:CQRS 可以使用普通事务表,事件溯源聚合也可以直接提供简单读取。应针对不同压力分别选择。CQRS 会引入投影延迟和重建操作;事件溯源会引入事件演进、重放确定性、存储增长与纠错流程。快照只能加速重放,是派生数据,不是权威历史。
可观测性
5个问题 · 0 已看32 生产日志事件应该包含什么,又必须排除什么? 查看答案 ▾ 收起 ▴
日志事件应包含稳定事件名、级别、时间戳、服务与版本、操作或关联标识,以及解释结果所需的结构化字段。应在所有权边界记录,而不是每一层都记录同一失败后再抛出。可用时加入 trace ID 与 span ID,但日志仍应能独立检索。绝不能记录密码、令牌、私钥或原始敏感载荷;字段分类与脱敏必须在发送前完成,不能只依赖日志后端。还要控制高基数字段与总量,避免事故期间日志成本失控。好的事件能直接回答具体诊断问题,而不需要解析散文。
33 分布式追踪上下文怎样安全跨越服务边界? 查看答案 ▾ 收起 ▴
插桩会为有意义的操作创建 span,并通过受支持的请求或消息元数据传播 trace 标识与采样信息。接收方提取并校验上下文,再按关系创建子 span 或链接;异步扇出可能需要链接,不能假装所有工作都属于一条严格调用栈。不要无差别传播 baggage,因为它会跨越信任边界增加字节数、基数与敏感数据风险。采样决策必须足以组装有用的端到端追踪。错误和关键属性要限制基数,追踪不适合承载的细节应交给日志或指标。
34 怎样把客户端错误契约与内部诊断信息分开? 查看答案 ▾ 收起 ▴
客户端响应应包含稳定的机器可读代码、安全的人类消息、相关字段详情与关联标识,并使用反映协议结果的 HTTP 状态。不要暴露堆栈、SQL、依赖地址、秘密或不稳定的异常类名。内部应把预期运维失败与编程缺陷分开分类,保留原因链,并由拥有处理职责的边界只记录一次结构化上下文。领域失败要明确映射,不能把所有异常都变成 500。遇到意外失败时,客户端只获得通用重试策略与关联 ID,详细诊断和告警仅发送到受控系统。
35 什么条件能把故障注入变成有效的混沌实验? 查看答案 ▾ 收起 ▴
先提出与用户或业务行为相关、可度量的稳态假设,再注入一种真实故障,并控制范围与持续时间。开始前要定义中止条件、值守人员、回退方式、排除的关键时段,以及最小有效影响半径。观察重点是用户结果与系统机制,而不只是注入工具是否运行。例如延迟实验可以预测:某个依赖变慢时,结账成功率仍高于约定阈值。若假设失败,应立即停止、保留证据、修复弱点并重新实验。反复执行的安全实验能验证韧性;无边界的随机破坏只会制造事故。
36 服务网格能提供哪些可观测信息,又无法知道什么? 查看答案 ▾ 收起 ▴
网格数据平面可以观察经过代理的传输层请求,并统一生成连接、延迟、响应码、重试与双向 TLS 遥测。控制平面负责分发路由、安全和遥测配置,不位于正常数据路径上。这种视角无法可靠判断业务是否成功、哪些租户受影响、队列中的工作、本地调用,或绕过捕获的流量。加密或流式协议也可能限制语义细节。在 Istio 中,要验证工作负载纳管、流量捕获、协议识别、采样与标签基数。领域结果仍需应用指标和 span,同时还要评估网格增加的延迟、资源与运维成本。
没有符合筛选条件的问题。