Docker中PHP gRPC客户端无法连接Kubernetes端口转发服务
问题:Docker容器内PHP gRPC客户端无法连接Kubernetes端口转发服务,grpcurl却正常
环境背景
- 在Kubernetes中部署了
reporter-devDeployment,通过以下命令做端口转发:kubectl port-forward deploy/reporter-dev 8585:8081 --address 0.0.0.0 - 本地主机(IP:192.168.31.205)用Postman访问
192.168.31.205:8585可正常收到Kubernetes服务响应 - Docker容器内的PHP gRPC客户端无法建立连接,但容器内用
grpcurl执行相同请求却能正常获取结果
PHP gRPC客户端代码
GroupService类
class GroupService { private ReportGroupsClient|BaseStub|null $reportGroupsClient; public function __construct() { $this->reportGroupsClient = Yii::$container->get( ReportGroupsClient::class, ['192.168.31.205:8585', [ 'credentials' => ChannelCredentials::createInsecure(), ]] ); } public function getReportGroupsList() { $res = $this->reportGroupsClient->GetList(new ReportGroupsGetListRequest([ 'limit' => 10, 'offset' => 0, ]))->wait(); // exec('/var/www/grpcurl -insecure 192.168.31.205:8585 retail.reporter.ReportGroups/GetList', $res); return $res; } }
调用代码
public function actionHealth(): void { $this->log("Start DEBUG gRPC"); $rr = new GroupService(); $res = $rr->getReportGroupsList(); var_dump($res); $this->log("End of debug"); }
错误日志
/var/www # GRPC_VERBOSITY=debug GPRC_TRACE=all php yii reports/report/health I0210 07:22:57.540640544 357 ev_epoll1_linux.cc:121] grpc epoll fd: 4 D0210 07:22:57.540835960 357 ev_posix.cc:171] Using polling engine: epoll1 D0210 07:22:57.541246752 357 lb_policy_registry.cc:42] registering LB policy factory for "grpclb" D0210 07:22:57.541344669 357 lb_policy_registry.cc:42] registering LB policy factory for "rls_experimental" D0210 07:22:57.541406252 357 lb_policy_registry.cc:42] registering LB policy factory for "priority_experimental" D0210 07:22:57.541479794 357 lb_policy_registry.cc:42] registering LB policy factory for "weighted_target_experimental" D0210 07:22:57.541527044 357 lb_policy_registry.cc:42] registering LB policy factory for "pick_first" D0210 07:22:57.541548752 357 lb_policy_registry.cc:42] registering LB policy factory for "round_robin" D0210 07:22:57.541621877 357 lb_policy_registry.cc:42] registering LB policy factory for "ring_hash_experimental" D0210 07:22:57.541887044 357 certificate_provider_registry.cc:33] registering certificate provider factory for "file_watcher" D0210 07:22:57.541919794 357 lb_policy_registry.cc:42] registering LB policy factory for "cds_experimental" D0210 07:22:57.541977919 357 lb_policy_registry.cc:42] registering LB policy factory for "xds_cluster_impl_experimental" D0210 07:22:57.542039169 357 lb_policy_registry.cc:42] registering LB policy factory for "xds_cluster_resolver_experimental" D0210 07:22:57.542087877 357 lb_policy_registry.cc:42] registering LB policy factory for "xds_cluster_manager_experimental" 2023-02-10 07:22:57 Start DEBUG gRPC D0210 07:22:57.649119960 357 dns_resolver.cc:162] Using native dns resolver I0210 07:22:57.652611710 359 socket_utils_common_posix.cc:429] Disabling AF_INET6 sockets because ::1 is not available. I0210 07:22:58.759204128 357 subchannel.cc:948] subchannel 0xffff81952db0 {address=ipv4:192.168.31.205:8585, args=grpc.client_channel_factory=0xffff8195d050, grpc.default_authority=192.168.31.205:8585, grpc.internal.channel_credentials=0xffff81916b90, grpc.internal.security_connector=0xffff8191be30, grpc.internal.subchannel_pool=0xffff8191a740, grpc.resource_quota=0xffff8191c420, grpc.server_uri=dns:///192.168.31.205:8585}: connect failed: {"created":"@1676013778.758779961","description":"Endpoint read failed","file":"/tmp/pear/temp/grpc/src/core/ext/transport/chttp2/transport/chttp2_transport.cc","file_line":2572,"occurred_during_write":0,"referenced_errors":[{"created":"@1676013778.758739461","description":"Socket closed","fd":6,"file":"/tmp/pear/temp/grpc/src/core/lib/iomgr/tcp_posix.cc","file_line":802,"grpc_status":14,"target_address":"ipv4:192.168.31.205:8585"}]} I0210 07:22:58.759450044 357 subchannel.cc:888] subchannel 0xffff81952db0 {address=ipv4:192.168.31.205:8585, args=grpc.client_channel_factory=0xffff8195d050, grpc.default_authority=192.168.31.205:8585, grpc.internal.channel_credentials=0xffff81916b90, grpc.internal.security_connector=0xffff8191be30, grpc.internal.subchannel_pool=0xffff8191a740, grpc.resource_quota=0xffff8191c420, grpc.server_uri=dns:///192.168.31.205:8585}: Retry immediately I0210 07:22:58.759495461 357 subchannel.cc:914] subchannel 0xffff81952db0 {address=ipv4:192.168.31.205:8585, args=grpc.client_channel_factory=0xffff8195d050, grpc.default_authority=192.168.31.205:8585, grpc.internal.channel_credentials=0xffff81916b90, grpc.internal.security_connector=0xffff8191be30, grpc.internal.subchannel_pool=0xffff8191a740, grpc.resource_quota=0xffff8191c420, grpc.server_uri=dns:///192.168.31.205:8585}: failed to connect to channel, retrying array(2) { [0]=> NULL [1]=> object(stdClass)#241 (3) { ["metadata"]=> array(0) { } ["code"]=> int(14) ["details"]=> string(34) "failed to connect to all addresses" } } 2023-02-10 07:22:58 End of debug
疑问
既然Docker容器内grpcurl可以正常请求,说明网络连通性没问题,那PHP gRPC客户端连接失败的可能原因是什么?
可能的原因分析
- PHP gRPC扩展版本与服务端不兼容:检查PHP安装的gRPC扩展版本,和Kubernetes服务端使用的gRPC版本是否存在兼容性问题。比如服务端用了较新的HTTP/2特性,而旧版本的PHP扩展不支持。
- 客户端连接配置缺失:尝试在gRPC客户端配置中显式指定
grpc.enable_http_proxy为false,或者添加'grpc.http2.max_pings_without_data' => 0等参数,避免不必要的HTTP代理干扰或ping超时。 - DNS解析异常:虽然用了IP地址,但PHP gRPC扩展可能仍会走DNS解析流程。可以尝试在客户端配置中添加
'grpc.default_authority' => '192.168.31.205:8585',或者直接使用ipv4:前缀的地址格式,比如'ipv4:192.168.31.205:8585'。 - Socket权限或资源限制:PHP进程的用户权限可能无法创建或维持gRPC所需的socket连接。检查Docker容器内PHP进程的运行用户,以及系统的ulimit资源限制(比如文件句柄数)。
- HTTP/2协议协商失败:PHP gRPC扩展的HTTP/2实现可能存在问题,尝试强制客户端使用HTTP/1(虽然gRPC默认用HTTP/2,但部分场景下可通过配置调整),或者检查容器内是否有拦截HTTP/2流量的代理或防火墙。
内容的提问来源于stack exchange,提问作者Makinaru
相关产品推荐
相关产品推荐

