学完这篇,你能用 PHP 把一套单体应用拆成两三个可独立部署的服务,并让它们自己注册、互相发现、从配置中心动态读配置——整套跑在你自己的机器上。
第一步:先判断边界,别急着拆
拆分的唯一依据是「业务能力」,不是「技术分层」。一个论坛/商城类系统,第一批该拆出来的通常是这三个:
- 用户服务:账号、登录、权限
- 业务主服务:帖子/订单这类核心流程
- 通知服务:站内信、邮件、推送
判断标准很简单:这个模块的发布节奏和扩容需求,是不是明显跟主站不一样。通知服务天天改模板、主站一个月发一次版——这才值得拆。
注意:不要拆出「用户表服务」「日志服务」这种按数据表或技术层切的东西。结果是一次请求跨 4 个服务,跨库 JOIN 全靠手写循环,性能比单体还差。
拆完第一件事:每个服务独占自己的库,不允许跨库 JOIN。做不到这点,先别往下走。
第二步:让 PHP 跑起常驻进程
php-fpm 是「一个请求一次生命周期」,做微服务会把连接建立、框架启动的开销放大好几倍。所以先换成常驻内存的运行时:
pecl install swoole
composer create-project hyperf/hyperf-skeleton order-service
cd order-service && php bin/hyperf.php start
`php bin/hyperf.php start` 就是启动命令,默认监听 9501。第二个服务同理,起在 9502。
注意:常驻内存意味着全局变量、静态属性、单例在请求之间是共享的。千万别往 `static $currentUser` 里塞请求级数据,否则 A 用户会看到 B 用户的数据。这是从 fpm 转过来最容易翻车的地方。
第三步:接入注册中心(以 Nacos 为例)
先起一个 Nacos:
docker run -d --name nacos -p 8848:8848 -p 9848:9848 \
-e MODE=standalone nacos/nacos-server:v2.3.0
控制台地址 `http://127.0.0.1:8848/nacos`,默认账号密码都是 `nacos`。
然后在每个服务里装组件:
composer require hyperf/service-governance hyperf/service-governance-nacos
编辑 `config/autoload/services.php`,在 `drivers` 下配置 `nacos` 驱动,填上 `host` 和 `port`。服务启动时会以临时实例身份注册进去,SDK 每 5 秒发一次心跳,进程挂了实例自动摘除。
调用方不用写死 IP,直接请求服务名:
http://user-service/api/user/1
负载均衡组件会自动从 Nacos 拉可用实例列表,按轮询挑一台。
注意两个高频坑:① Nacos 2.x 除了 8848,还需要放行 gRPC 端口 9848/9849,只开 8848 会表现为「注册上了但心跳超时」;② 在 Docker 里跑的服务,注册上去的是容器内网 IP,宿主机调不通,需要显式指定网卡或注册固定 IP。
第四步:接配置中心
不要每个服务自己维护一份 `config/autoload/*.php`。在 Nacos 控制台「配置管理→新建配置」建一条:
- Data ID:`order-service.yaml`
- Group:`DEFAULT_GROUP`
- 内容:就是普通的 YAML 键值对
服务端装 `composer require hyperf/config-nacos`,在 `config/autoload/config_center.php` 里填同样的 Data ID 和 Group。
之后改配置,在控制台点发布,服务不用重启——Nacos 通过长轮询把变更推下来,本地缓存刷新即可。
注意:代码里必须留兜底默认值。配置中心如果刚好在服务启动瞬间不可用,没有默认值服务直接起不来。另外数据库密码这类敏感项别明文提交到 Git,配置中心只存一份。
第五步:跑通一次完整调用
启动两个服务,回 Nacos 控制台看「服务管理→服务列表」,实例数应该是 1。然后从网关或订单服务发一次请求打到用户服务,能拿到数据就通了。
上线前补三件事:
- 超时:HTTP 调用设 500ms,别用默认的无限等待
- 重试:最多重试 1 次,且只重试幂等的 GET
- 链路 ID:网关生成一个 trace id,一路透传到最下游
注意:重试一定要设上限。A 调 B 超时、B 其实没挂只是慢,A 再重试只会把 B 压死,这就是雪崩的起点。
小结
- 按业务能力拆,每个服务独占自己的库,不跨库 JOIN
- PHP 做微服务先换 Swoole/Swow 常驻运行时,同时警惕静态变量污染
- 注册中心用临时实例 + 心跳,调用方写服务名而不是 IP
- Nacos 2.x 记得放行 9848/9849
- 配置中心要有本地兜底值,别把启动依赖押在它身上
- 超时必须设,重试必须有上限,否则慢请求会变成雪崩