doctrine migrations需按服务隔离配置:每个微服务使用独立数据库或schema,migrations_paths按服务划分路径,禁用全局migrate命令,改用--em指定实体管理器,迁移脚本严禁跨表操作。

不能直接“拆”,得先让单体具备可拆性——核心是解耦、隔离、可观测。没做这三件事就动刀,90%会卡在数据库共享、服务间强依赖、测试断崖式失效上。
Doctrine Migrations 怎么配置才不炸库
单体拆分时最常踩的坑:所有服务还连着同一个数据库,migration 一跑,User Service 的 up() 把 Order Service 依赖的字段删了。
- 每个微服务必须有独立数据库实例(哪怕初期共用物理库,也要用不同 schema 或前缀隔离)
-
doctrine_migrations.yaml中的migrations_paths必须按服务划分,比如:'App\Migrations\User': '%kernel.project_dir%/src/User/Migrations' - 禁用全局
doctrine:migrations:migrate;改用服务级命令:php bin/console doctrine:migrations:migrate --em=user(需提前配好多个 entity manager) - 迁移脚本里禁止跨服务表操作——
ALTER TABLE order DROP COLUMN user_name这类语句必须删掉,改用 API 同步或事件补偿
Symfony Messenger 如何避免消息乱序和丢失
用 Messenger 做服务间异步通信很常见,但默认配置下,订单创建后发的 OrderPlaced 消息可能比用户积分更新消息晚到,导致状态不一致。
- 关键配置项
transactional: true必须开启(已在doctrine_migrations.yaml示例中体现),否则 DB 提交和消息发送不在同一事务 - 不要把所有消息塞进一个 transport;按业务重要性分级:
critical走amqp://(RabbitMQ),notification走redis://,log走in_memory - 消费者端必须实现幂等:在处理
OrderShipped消息前,先查本地是否已存在该shipment_id记录 - 别信
retry_strategy默认值;对支付回调类消息,建议显式设max_retries: 5+delay: 1000(毫秒)
API Platform + JWT 怎么切出独立认证服务
单体里 User 实体和登录逻辑常被各模块直调,拆成 User Service 后,其他服务没法再 new UserRepository(),必须走 API。
- 认证服务只暴露两个端点:
POST /api/login_check(返回 JWT)和GET /api/me(校验 token 并返回用户基础信息) - 其他服务不再集成
LexikJWTAuthenticationBundle,改用HttpClient调用认证服务的/api/me,并缓存结果(TTL 设为 token 有效期的 80%) - JWT 的
user_id字段必须保留,但禁止携带角色、权限等敏感字段;权限校验逻辑下沉到各服务内部,基于从认证服务拿到的user_id查本地授权表 - 别在网关层做 token 校验——Symfony 的
security.yaml里jwtguard 必须保留在认证服务内,其他服务用http_basic或自定义 guard 调用它
最难的不是写代码,是让团队接受“一个功能上线要等三个服务都通过契约测试”。契约文件(Pact 或 OpenAPI spec)得由消费者先写,提供者只是实现——这点反直觉,但跳过它,拆分后的联调会变成黑洞。











