Skip to content

Spring排障:输入、代理、事务与冲突 ​

前置:能沿控制器到服务、Repository读取调用链。排查对象是任务API完整源码中的Errors、TaskService和application.properties。示例未执行;命令与现象均为读者未来自行验证的步骤和预期,不能视为运行记录。

Spring返回400时应该先检查哪里 ​

Spring返回400时应该先检查哪里?400首先定位到请求边界:JSON是否完整、title/done是否存在、title是否空白或过长、version是否字符串且格式规范。另核对Content-Type是否为application/json;不支持的媒体类型通常由框架返回415,不能一并归为400。数字ID在URL中天然是文本,但不得有前导零、负号、小数或超Long范围;JSON中的version也不得用Number发送。未知字段由Jackson拒绝,避免拼错done变成静默默认值。

查看响应code/message和服务端异常类型,区分消息转换失败、Bean Validation失败和服务范围检查。不要靠关闭全部校验“修复”400,也不要把所有400统一重试。要增加字段级错误可扩展错误DTO及契约;本例保持通用消息,避免回显请求内容或异常堆栈。

Spring找不到Bean或事务没有生效如何排查 ​

Spring找不到Bean或事务没有生效如何排查?先检查包扫描边界和注解:TasksApplication位于notes.tasks,相关组件在同包,Repository由Boot自动配置发现。缺依赖检查pom与已解析依赖树,不能随手复制不匹配版本的jar。构造器循环依赖应拆分责任,不把允许循环作为首选修复。

事务异常则检查调用是否经过代理:控制器调用公开服务方法、方法是否被同类自调用、异常是否被吞掉、是否在异步线程丢失原事务上下文。flush成功不代表提交成功,readOnly也不保证禁止写。定位时观察服务边界与日志,在本例未运行条件下只能说明排查顺序,不能声称已重现或修复环境故障。

Spring出现409后应该自动重试吗 ​

Spring出现409后应该自动重试吗?409说明读取以来状态已变化,应重读当前任务并让使用者合并草稿,再以当前版本提交。直接换成最新version并重发旧内容会覆盖别人的修改,失去版本保护的意义。前端保留错误和重新加载入口,并明确重新加载会丢弃草稿;后端仍通过@Version覆盖并发窗口。

网络超时与409不同:超时可能发生在服务已经提交之后,因此不能据此断定写入失败。POST没有幂等键,自动重试可能创建重复任务;先重读列表核实。PUT和DELETE也先核实当前版本或是否存在。需要可靠自动重试时,另设计幂等键、请求记录和重放语义,不能把乐观锁当作完整幂等机制。

Spring重启丢数据或500应该怎样定位 ​

Spring重启丢数据或500应该怎样定位?重启后任务消失符合内存H2的教学契约,先确认连接串和create-drop配置,再决定是否引入持久化及迁移。不要把DB_CLOSE_DELAY=-1解释成跨进程持久化。列表少于总数据也可能来自前100条限制,先确认排序与查询边界。

500从服务端日志检查数据库连接、SQL约束、事务提交和序列耗尽等原因;客户端只见通用消息。不能把所有数据库故障映射409,只有乐观版本冲突对应409;其他异常仍需判断可恢复性。本文未运行服务和数据库,所有故障现象均为推理与预期。框架依据见Spring MVC校验与JPA锁。

练习:从症状选择下一步 ​

出现四个报告:重启任务消失;新建任务超时后列表多了一项;编辑收到409;对API使用错误HTTP方法收到405。分别给出下一步,判断哪些可直接自动重试。

参考答案(推演,未执行)

重启消失先核对内存H2和create-drop,属于教学生命周期;需要持久化时另选存储和迁移。超时可能已提交,先重读列表,不自动重试无幂等键的POST。409重读当前任务、合并草稿再提交,不偷换版本强行覆盖。405检查方法与契约,保留框架状态而非改成500,修正调用;直接重发相同错误请求没有价值。这四类均不适合无条件自动重试。

继续阅读