Consul服务注册失败主因是curl未设Content-Type: application/json或json_encode()输出为false;健康检查应据服务暴露方式选http(需/health端点)或tcp(仅验端口);KV读取需校验key路径与ACL token;服务发现须加?passing&dc=参数。

Consul服务注册为什么总失败?检查curl和JSON格式
PHP调用Consul API注册服务时最常见的失败,不是权限或网络问题,而是curl没设Content-Type: application/json,或者json_encode()后没校验输出是否为false(比如含非UTF-8字符)。Consul的/v1/agent/service/register端点严格拒绝非JSON请求体。
- 必须用
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']) -
$body = json_encode($serviceConfig)之后立刻加if ($body === false) { throw new Exception('JSON encode failed: ' . json_last_error_msg()); } - 服务名里不能含空格或斜杠,否则Consul返回
400 Bad Request,错误信息是"Invalid service name"
健康检查用http还是tcp?看你的服务暴露方式
Consul健康检查类型直接影响PHP服务能否被正确标记为passing。如果PHP服务只监听127.0.0.1:8080且未开防火墙,用http检查会因Consul agent无法访问而持续critical;此时应改用tcp检查端口连通性,或把服务绑定到0.0.0.0并确保http路径返回200。
-
http检查需服务提供/health等轻量端点,返回HTTP 200,响应体可为空 -
tcp检查只验证端口是否可连,不发任何应用层数据,适合CLI守护进程或无HTTP层的Swoole协程服务 - 避免用
script类型检查——它依赖Consul agent本地执行PHP命令,在容器或无shell环境必然失败
consul kv get读不到PHP配置?确认key路径和ACL token
PHP从Consul KV读取配置时返回空,大概率是key路径写错(比如漏了前缀php/app/)或ACL token没传。Consul默认关闭ACL,但一旦启用,所有GET /v1/kv/...请求都必须带X-Consul-Token头,否则静默返回[]。
- key路径区分大小写,
php/config/db≠PHP/config/db - 用
curl -H "X-Consul-Token: xxx" http://localhost:8500/v1/kv/php/config/db?raw手动测试,确认能拿到明文值 - PHP中用
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-Consul-Token: ' . $token]),不要拼在URL里(会被日志泄露)
服务发现返回空数组?检查PassingOnly和Datacenter
调用/v1/health/service/{name}时PHP收到空数组,通常是因为没加passing参数,或者目标服务在别的数据中心。Consul默认返回所有状态的服务实例,包括critical和warning,但PHP业务代码往往只想要健康的,所以必须显式加?passing;另外跨DC查询要指定dc=xxx参数,否则只查本地DC。
立即学习“PHP免费学习笔记(深入)”;
- 健康实例查询URL应为
/v1/health/service/user-service?passing&dc=prod-dc - 返回结果里的
Service.Address可能是""(表示用Node.Address),别直接拼接http://前缀 - 若Consul集群启用了gRPC代理,PHP客户端仍走HTTP API即可,无需改逻辑——gRPC只影响内部通信
passing状态,期间查不到实例是正常的。



















