LLM 安全与 Spring Modulith

共 26 题
📑 题目列表 26 题
#
★★★

1. Modulith 与 Event Sourcing 的集成

Spring Modulith 与 Event Sourcing 如何集成?事件模型与持久化如何配合?

  • Modulith 的模块事件机制
  • Event Sourcing 的事件为中心建模
  • 事件持久化与回放的一致性

Spring Modulith 提供模块间事件发布机制(@ApplicationModuleListener),天然适合与 Event Sourcing 的事件驱动建模结合。事件作为模块间协作的载体,被持久化到事件发布表(如 JdbcEventPublicationRegistry),通过异步重放保证事件不丢失。Event Sourcing 把状态变更建模为事件流,Modulith 则把这些事件在模块边界上规范发布与订阅,二者结合既能解耦模块,又能通过事件日志实现溯源与重建。

集成的关键是把"领域事件"与"模块事件"统一。Modulith 提供事件发布的可靠管道与持久化,Event Sourcing 提供事件驱动的领域建模,结合后模块解耦更彻底、变更可追溯,同时共享事务一致性保障。

#
★★★

2. Modulith 与 Saga 模式的边界

Modulith 与 Saga 模式的边界如何划分?两者是什么关系?

  • Modulith 的模块内事务边界
  • Saga 的跨服务长事务编排
  • 各自适用场景的区分

Spring Modulith 面向单体模块化,强调同一进程内模块间的依赖与事务边界,事务通常仍在一个数据库/Boundary 内。Saga 模式面向分布式事务,把一个跨服务的长事务拆分为多个本地事务,通过补偿(compensation)保证最终一致性。Modulith 的模块事件可在模块间协作,但当协作跨越独立服务或需要补偿时,才需要 Saga 编排。边界在于:模块内用 Modulith 的本地事务,跨服务长流程用 Saga。

二者的边界是"单体模块化 vs 跨服务分布式"。Modulith 让单体内部保持松耦合与事务可控,Saga 解决跨服务一致性。理解边界可避免在单体内过度引入 Saga 复杂度,或在分布式场景错误依赖本地事务。

#
★★★

3. Modulith 单元(@UnitOfWork)与跨模块事务

Spring Modulith 的 @UnitOfWork 与跨模块事务如何工作?它解决的问题是什么?

  • @UnitOfWork 的事务边界
  • 事件与事务的原子性
  • 跨模块调用的一致性保证

@UnitOfWork 用于把事件发布与业务变更纳入同一个事务边界,保证事件发布与应用状态变更的原子性:要么一起提交,要么一起回滚。Spring Modulith 通过事件发布注册表在这个事务内记录待发布事件,事务提交后再异步投递,从而避免"业务成功但事件未发"或"事件发出但业务回滚"的不一致。这让模块间通过事件协作时获得可靠的一致性。

跨模块一致性的难点在于业务变更与事件发布的原子性。@UnitOfWork 把两者绑定在同一事务,再配合事务后投递,既保证原子性又避免阻塞,是模块化事件协作的可靠性基石。

#
★★★

4. Modulith 的 JPA 持久化与事务边界

Spring Modulith 如何与 JPA 持久化配合?事务边界如何划分?

  • 模块内 JPA 实体的边界
  • 事务边界与模块边界的关系
  • 跨模块数据访问的约束

Spring Modulith 鼓励每个模块拥有自己的领域边界,JPA 实体与 Repository 归属于所属模块,模块间不直接访问彼此实体,而是通过应用服务或事件协作。事务边界通常与模块边界对齐,一个模块内的业务操作在一个事务中完成。跨模块时避免依赖内部实体,通过公开 API 或事件传递数据,从而保持模块的封装性与事务的可控性。

JPA 持久化与模块化的配合核心是"实体归属模块"。把持久化对象收敛在模块内,避免跨模块直接操作他人实体,能防止模块腐化,同时让事务边界清晰,便于维护与演化。

#
★★★

5. Modulith 的依赖注入(Autowired 与模块边界)

Spring Modulith 中依赖注入(Autowired)如何与模块边界协同?跨模块注入有何约束?

  • 模块内 Bean 的自动注入
  • 跨模块依赖的边界约束
  • 依赖检查对腐化的防护

在 Spring Modulith 中,模块内 Bean 的 Autowired 依赖注入正常工作,但模块间的依赖被约束在模块边界上:一个模块只能依赖另一个模块的公开 API(如以 *.api 包命名的类型),而不能注入其内部实现。Modulith 的依赖检查(ModulithVerify/ArchUnit)会验证这些依赖规则,检测越界依赖,防止模块化腐化。

依赖注入本身不破坏模块化,破坏的是"注入内部实现"。通过公开 API 约定与依赖检查,把 Autowired 限定在合法边界内,既保留 Spring 的便利,又维持模块的封装与可演化性。

#
★★★

6. Spring Modulith 的事件持久化(JdbcEventPublicationRegistry)与事务一致性的协作

JdbcEventPublicationRegistry 如何实现事件持久化?它与事务一致性如何协作?

  • 事件写入发布表的持久化机制
  • 事务提交后的事件投递
  • 重试与去重的一致性保障

JdbcEventPublicationRegistry 将待发布事件写入数据库的发布表,与业务变更在同一事务内完成,保证"业务成功则事件已记录"。事务提交后,异步投递器从发布表读取并投递事件,投递成功后标记完成。若投递失败,可在后续重试;消费者侧通过幂等/去重避免重复处理。这一机制把事件发布的可靠性从内存提升到数据库,与业务事务形成一致性闭环。

事件持久化的核心是"记录与投递分离"。先在同一事务持久化事件,再异步投递,配合失败重试与幂等消费,既保证不丢失,又避免业务与事件不一致,是模块化事件协作的可靠保障。

#
★★

7. token 用量如何计量并按租户/业务做成本归因,配额限流与预算告警应落在哪一层实现

token 用量应如何计量并按租户/业务归因成本?配额限流与预算告警应落在哪一层?

  • token 用量的采集与计量
  • 按租户/业务维度的成本归因
  • 配额限流与预算告警的层次

token 用量可在模型调用层通过响应元数据采集输入/输出 token,并携带租户、业务、模型等标签,利用 Micrometer 指标上报,实现按租户/业务维度的成本归因。配额限流应落在调用入口或网关层,在进入模型前按租户配额拦截超限请求,避免成本失控;预算告警则基于聚合指标在监控层设置阈值,接近预算时告警并触发降级。限流前置、计量后置、告警聚合,分层实现成本治理。

成本治理需要"计量-限流-告警"三层配合。计量负责归因,限流防止超支,告警驱动预警。落点选择上,限流靠前拦截,计量贯穿调用,告警基于聚合,这样才能在控制成本的同时保持可观测。

#
★★

8. 模型不可用或超时的降级策略如何设计,备用模型切换、语义缓存应答与熔断如何协同保障可用性

模型不可用或超时时降级策略如何设计?备用模型切换、语义缓存与熔断如何协同?

  • 备用模型的自动切换
  • 语义缓存对重复请求的应答
  • 熔断防止故障扩散

降级由多层协同:流式主模型失败或超时可自动切换到备用模型(如从云端切本地或切另一提供商),保证基本可用;语义缓存对语义相似的重复请求直接返回缓存结果,减少模型调用、提升响应速度;熔断器在模型持续失败时快速打开,避免请求堆积与成本放大,进入预设降级路径。三者结合,缓存过滤重复、熔断隔离故障、备用承接流量,共同保障模型依赖下的系统可用性。

模型是不可控的外部依赖,降级是可用性保障的核心。语义缓存降低对模型的依赖,熔断防止故障连坐,备用模型兜底承接,三层递进既降低开销又提升韧性。

#
★★

9. Modulith 与 Micrometer Tracing 的模块边界

Spring Modulith 与 Micrometer Tracing 如何配合?模块边界在追踪中如何体现?

  • 跨模块调用的追踪贯穿
  • 模块维度作为追踪标签
  • 故障定位与可观测性

Micrometer Tracing 可为跨模块的方法调用与事件处理生成分布式追踪,把一次请求在多个模块间的流转串联成 trace。Spring Modulith 可通过在模块边界注入追踪标签(如模块名),让追踪数据反映模块维度,便于按模块定位性能瓶颈与故障。二者结合在模块化单体中保留了分布式的可观测能力。

模块化单体的可观测性要点是"看到模块间的调用关系"。Tracing 提供链路,模块标签提供维度,结合后能清晰呈现请求在模块间的路径,支撑性能分析与线上排障。

#
★★

10. Modulith 与 Spring Cloud Function 的边界

Spring Modulith 与 Spring Cloud Function 的边界如何划分?两者如何协作?

  • Modulith 的模块化组织职责
  • Spring Cloud Function 的函数抽象
  • 业务函数与部署形态的分离

Spring Modulith 负责把单体按业务模块组织,约束模块边界与依赖;Spring Cloud Function 提供统一的函数抽象(Function/Supplier/Consumer),让业务逻辑以函数形式暴露,可部署为 HTTP、消息、事件等多种形态。边界在于:Modulith 规定"模块怎么划分",Cloud Function 规定"能力怎么暴露"。二者可协作,模块内的业务逻辑以函数暴露,由 Cloud Function 适配不同触发源。

二者解决不同问题:模块化组织与函数化暴露。Modulith 保证内部结构清晰,Cloud Function 保证对外能力可移植,结合使模块既能内部解耦,又能灵活适配多种部署形态。

#
★★

11. Modulith 的 Module Testing 与 Verifies

Spring Modulith 如何进行 Module Testing,Verifies 起什么作用?

  • 模块级测试的边界切片
  • 对模块内行为的验证
  • 模块结构验证(ApplicationModules.verify())与模块级测试

Spring Modulith 提供模块级测试支持,通过测试切片只加载单个模块的上下文,验证该模块在隔离环境下的行为,相比全应用测试更快、更聚焦。模块结构验证使用 ApplicationModules.of(Application.class).verify()(可结合 jMolecules ArchUnit 规则与 VerificationOptions)校验模块依赖规则;模块级测试使用 @ModuleTest/@ApplicationModuleTest 实现隔离验证。二者让模块在不启动整个应用的前提下得到有效验证。

模块测试的价值是"隔离验证 + 快速反馈"。只加载目标模块上下文,能快速发现模块内问题;模块结构验证(verify())与模块级测试相结合,使模块化应用在演化中保持结构健康。

#
★★

12. Modulith 的 documentation.md 自动生成

Spring Modulith 如何自动生成 documentation.md?它有什么工程价值?

  • 模块结构与依赖的自动提取
  • 文档的自动生成机制
  • 文档与代码的一致化

Spring Modulith 能从代码中自动提取模块结构、模块内组件、模块间依赖关系,并生成 documentation.md 文档,展示模块划分与依赖图。文档随代码自动更新,避免了手工维护架构文档的滞后与失真。它让团队能直观看到模块边界与依赖,作为架构治理与新人上手的有效载体。

自动生成文档的价值是"文档即代码的副产品"。从真实代码提取结构,保证文档与实现一致,降低维护成本,同时以文档形式暴露架构,便于评审与治理。

#
★★

13. Modulith 的事件发布(@ApplicationModuleListener)

@ApplicationModuleListener 如何实现模块间事件发布?它有什么特点?

  • 注解式监听事件
  • 事件驱动的模块间解耦
  • 异步与事务性保障

@ApplicationModuleListener 标注在方法上,用于监听其他模块发布的事件,是模块间事件协作的入口。配合 Spring Modulith 事件发布机制,事件在事务内发布、异步投递,监听方法在事件到达时被调用。它让模块通过事件而非直接调用解耦,同时获得事务性、幂等与重试等保障。

事件监听是模块化协作的核心机制。@ApplicationModuleListener 提供声明式监听,事件管道保障可靠投递,使模块间松耦合协作成为可能,是 Modulith 事件驱动的基础。

#
★★

14. Modulith 的依赖检查(ModulithVerify)

Spring Modulith 的 ModulithVerify 如何检查模块依赖?它防止什么问题?

  • 模块依赖规则的验证
  • 循环依赖与越界依赖检测
  • 防止模块化腐化

ModulithVerify 会分析模块间的包依赖,验证是否符合模块边界规则,检测循环依赖、越界依赖(如依赖了他模块内部实现)、未声明的依赖等违规。它在构建或测试阶段运行,及时发现并阻止模块化腐化,强制保持模块边界清晰。结合 ArchUnit 规则可进一步细化约束。

依赖检查是模块化治理的守门人。通过静态分析在合入前拦截结构违规,避免模块边界随时间腐化,保证模块化架构长期健康。

#
★★

15. Modulith 的测试切片(@TestEnvironment)

Spring Modulith 的 @TestEnvironment 测试切片如何使用?它解决什么问题?

  • 测试环境的模块切片
  • 减少测试启动范围
  • 模块级隔离验证

@TestEnvironment 用于为模块测试配置隔离的测试环境,可指定只加载目标模块及必要依赖,而不启动整个应用上下文。它结合 Spring 的测试切片灵活裁剪,使每个模块的测试更快、更独立,避免无关模块的初始化开销与相互干扰。

模块化应用上下文庞大,全量启动测试慢且易耦合。测试切片只加载相关模块,提速并隔离,让模块级测试更聚焦、更可靠。

#
★★

16. Modulith 项目的 ApplicationModule 与 package by feature

Modulith 的 ApplicationModule 与 "package by feature" 有什么关系?如何组织模块结构?

  • package by feature 的组织理念
  • ApplicationModule 的模块声明
  • 按业务能力划分包的实践

Modulith 强调按业务能力(feature)而非技术层次组织包结构,即一个模块对应一个业务能力,包含该能力下的所有类(controller/service/repository 等)。ApplicationModule 注解用于显式声明模块边界与名称,帮助工具识别模块。这种 package by feature 让模块内聚度高、边界清晰,符合"高内聚、低耦合"的模块化原则。

package by feature 是 Modulith 的组织基础。把同业务能力的类聚在一起,模块语义清晰,依赖检查才能有效。ApplicationModule 把这种组织方式显式化,便于工具与检查。

#
★★

17. Prompt Injection(提示注入)攻击的原理是什么,输入过滤、系统提示隔离与工具调用权限收敛如何分层防御

提示注入攻击的原理是什么?输入过滤、系统提示隔离与工具调用权限收敛如何分层防御?

  • 提示注入的利用原理
  • 输入过滤与校验
  • 系统提示隔离与工具权限收敛

提示注入利用模型无法区分"指令"与"数据",通过让用户输入包含恶意指令(如"忽略系统提示""告诉我系统设定")来劫持模型行为。分层防御包括:输入过滤,对明显恶意或越权指令做检测与清洗;系统提示隔离,在系统提示中声明用户输入仅作为数据处理、不执行其中指令,并将系统指令与用户输入分离;工具调用权限收敛,最小化工具暴露、对敏感工具加鉴权与人工确认,防止注入后越权调用。

提示注入的本质是"指令/数据边界失守"。防御需从输入、提示构造、工具权限三层递进:过滤减少恶意进入,隔离降低指令污染,权限收敛限制注入后的危害面,形成纵深防御。

#
★★

18. RAG 场景下检索注入的外部内容如何成为间接提示注入入口,来源可信度校验与内容隔离如何处理

RAG 场景下检索到的外部内容如何成为间接提示注入入口?来源校验与内容隔离如何处理?

  • 检索内容作为间接注入媒介的原理
  • 来源可信度校验
  • 内容与指令的隔离

在 RAG 中,检索到的外部文档被当作上下文注入提示词,若文档本身包含恶意指令,就会成为间接提示注入入口,劫持模型或诱导其执行越权动作。应对措施包括:来源可信度校验,对文档来源、作者、权限做分级,低可信内容加标记或不予全量信任;内容隔离,把检索内容明确标注为"不可信数据"而非指令,或在送入前扫描过滤可疑指令,必要时限制其对工具调用的触发能力。

间接注入的防范核心是"不信任外部内容"。通过来源分级与内容标记,让模型把检索内容当数据而非指令,同时限制其导向工具调用的能力,缩小注入利用面。

#
★★

19. Spring Modulith 与 Gradle/Maven 多模块构建的工程取舍(构建工具差异对模块边界与依赖管理的影响)

Spring Modulith 与 Gradle/Maven 多模块构建如何取舍?构建工具差异对模块边界有何影响?

  • Modulith 逻辑模块与构建模块的关系
  • Maven/Gradle 的模块配置差异
  • 构建粒度对边界的影响

Modulith 的逻辑模块(ApplicationModule)与构建模块(Maven/Gradle 子模块)可以是不同维度:逻辑模块按业务能力划分,构建模块按编译与发布粒度划分。Maven 通过多 module 与依赖坐标管理子模块,Gradle 通过多 project 与 configuration 管理,构建模块之间的依赖会强化边界约束。取舍在于:构建模块过细会带来构建与维护成本,过粗则无法用构建约束强制边界。通常逻辑模块不必然对应构建模块,可结合 ArchUnit/ModulithVerify 在逻辑层做边界校验。

关键在于区分"逻辑边界"与"构建边界"。构建工具约束的是编译期依赖,逻辑层校验约束的是架构。合理取舍是逻辑模块内聚、构建粒度适中,并用构建依赖与静态检查共同守护边界。

#
★★

20. Spring Modulith 的 @Modulith/@ApplicationModule 注解

@Modulith 与 @ApplicationModule 注解分别有什么作用?如何使用它们声明模块化结构?

  • @Modulith 的根标注
  • @ApplicationModule 的模块声明
  • 注解驱动模块化识别

@Modulith 标注在应用入口类上,声明这是一个 Modulith 应用,并启用模块化支持(如事件发布、依赖检查、文档生成)。@ApplicationModule 标注在某个包上,显式声明这是一个应用模块,并指定模块名与对外 API 包。通过这两个注解,Spring Modulith 能识别模块边界、生成文档、执行依赖检查,把模块化结构显式化。

注解是模块化的"元数据"。@Modulith 声明应用整体,@ApplicationModule 声明具体模块,二者让框架与工具理解架构意图,从而启用事件、检查、文档等模块化能力。

#
★★

21. 如何在 Spring AI 中通过 Advisor 链统一实现审计日志、内容安全审查与合规留痕

如何通过 Spring AI 的 Advisor 链统一实现审计日志、内容安全审查与合规留痕?

  • Advisor 横切请求响应
  • 审计与安全审查的链式实现
  • 合规留痕的集中化

通过自定义 Advisor 挂载到 ChatClient 的 Advisor 链,可以在请求进入模型前与响应返回后统一执行横切逻辑。例如:一个 Advisor 记录请求与响应的审计日志(含用户、时间、token、内容摘要);一个 Advisor 对输入输出做内容安全审查,命中违规即拦截或脱敏;一个 Advisor 负责合规留痕,把敏感操作与结果持久化到审计存储。多个 Advisor 按序组成链,把分散的安全与合规逻辑集中化、可复用。

Advisor 链天然适合横切治理。把审计、安全、合规作为独立 Advisor 组合,既能统一管控又可独立演进,避免在业务代码中零散埋点,实现治理逻辑的标准化与可观测。

#

22. 当 LLM 可调用工具(function calling)时,越权与数据泄漏风险如何放大,最小权限与人工确认机制如何设计

LLM 可调用工具时越权与数据泄漏风险如何被放大?最小权限与人工确认机制如何设计?

  • 工具调用放大越权与泄漏风险
  • 最小权限原则的应用
  • 人工确认等高危操作兜底

当 LLM 能调用工具时,一个被注入或误判的请求可能触发读取敏感数据、修改数据、调用外部系统等操作,把越权与数据泄漏风险放大。对策是遵循最小权限:仅向模型暴露完成当前任务所需的最少工具,对敏感工具按角色/租户过滤,工具参数做白名单约束。对高风险操作(删除、转账、发布)加入人工确认机制,模型只生成调用意图,实际执行需人工审批,从而把误判与注入的影响限制在可控范围。

工具调用把模型从"只读生成"升级为"可执行操作",风险随之放大。最小权限收敛能力面,人工确认兜底高风险操作,二者结合在能力与安全之间取得平衡。

#

23. 模型输出幻觉(hallucination)与合规风险如何通过 grounding、引用溯源与人工审核流程加以约束

模型输出幻觉与合规风险如何通过 grounding、引用溯源与人工审核流程加以约束?

  • grounding 对事实性的约束
  • 引用溯源提升可信度
  • 人工审核兜底合规

幻觉指模型生成无依据或错误的内容。约束手段包括:grounding,把回答约束到检索到的可靠资料或结构化数据上,减少无中生有;引用溯源,要求回答给出资料来源或引用,便于核验与审计;人工审核流程,对高风险、高影响场景(如医疗、金融、发布类)设置人工复核,在自动生成无法保证合规时由人兜底。三者结合让模型输出既更可信又可追责。

幻觉无法根除,但可约束。grounding 从源头减少幻觉,引用溯源增加可核验性,人工审核兜底不可控场景,构成从"减少"到"追责"再到"兜底"的完整防线。

#

24. 结构化输出(Structured Output)被诱导越狱或返回非法结构时,校验 Advisor 与重试兜底的边界在哪里

结构化输出被诱导越狱或返回非法结构时,校验 Advisor 与重试兜底的边界在哪里?

  • 结构化输出的越狱与非法结构
  • 校验 Advisor 的拦截职责
  • 重试与兜底的分界

结构化输出可能被诱导越狱(突破约束返回非预期内容)或返回非法结构(字段缺失、类型错误)。校验 Advisor 负责在输出返回后校验结构是否合法、内容是否符合约束,拦截非法结果。重试兜底仅在"结构可修复、重试可能成功"时使用,例如让模型按 Schema 重新生成;若多次重试仍失败或检测到系统性越狱,则停止重试并返回安全兜底值或告警,避免无限循环与风险扩散。边界在于:校验负责判非,重试负责修复,兜底负责止损。

边界划分的原则是"可控修复则重试,不可控则止损"。校验区分结构非法与内容越狱,重试只用于可恢复的结构问题,系统性问题交给人或兜底,防止被诱导利用。

#

25. 请求/响应链路上的敏感信息(PII)如何在送入模型前脱敏,并在日志与审计中保留可追溯性

请求/响应链路上的敏感信息(PII)如何在送入模型前脱敏,并在日志与审计中保留可追溯性?

  • PII 的识别与脱敏
  • 送入模型前的数据替换
  • 日志审计中的可追溯性保留

在请求送入模型前,通过脱敏组件识别并替换敏感信息(如姓名、身份证、手机号、地址),用标记或假名替换真实值,模型只看到脱敏数据。响应对应字段再按映射还原或保持脱敏。为保留可追溯性,脱敏时建立原始值↔脱敏值的映射并安全存储,日志与审计记录脱敏后的数据及引用标识,既能满足安全合规,又能在需要时凭标识追溯原始请求。

PII 治理的核心是"模型不见明文,审计可追溯"。脱敏切断直连,映射保留关联,日志记录脱敏态与标识,实现安全与可追溯的平衡。

#

26. Modulith 与 Micronaut 的协同

Spring Modulith 与 Micronaut 能否协同?它们的关系与边界是什么?

  • Spring Modulith 的 Spring 依赖
  • Micronaut 独立框架定位
  • 集成方式与边界

Spring Modulith 构建在 Spring 生态之上,依赖 Spring 的 IoC 与事件机制,因此与 Micronaut(一个独立的、基于编译期 AOT 的框架)原生协同有限。若要在 Micronaut 中使用模块化思想,可采用与其生态兼容的方案,如 Micronaut 的模块化组织结合 ArchUnit 做依赖检查,或把 Spring Modulith 作为独立校验库在构建阶段使用。二者边界在于:核心模块化运行时能力依赖 Spring,Micronaut 项目需借助通用工具实现类似约束。

协同的关键是认清依赖。Spring Modulith 深度绑定 Spring,Micronaut 是独立框架,直接混用受限。实践中可在 Micronaut 项目借用其模块化理念与 ArchUnit 等通用校验,而非依赖 Spring 运行时。