跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

如何将Symfony单体应用拆分为微服务

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
里
jwt
guard 必须保留在认证服务内,其他服务用
http_basic
或自定义 guard 调用它 最难的不是写代码,是让团队接受“一个功能上线要等三个服务都通过契约测试”。契约文件(Pact 或 OpenAPI spec)得由消费者先写,提供者只是实现——这点反直觉,但跳过它,拆分后的联调会变成黑洞。

相关文章