You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenSearch PHP客户端生产环境插入文档报404 NotFoundHttpException

问题:Laravel中OpenSearch PHP客户端生产环境插入文档报404 NotFoundHttpException

问题描述

在Laravel应用中使用opensearch-project/opensearch-php客户端向OpenSearch的products索引插入文档时,仅生产环境出现404错误,开发/预发布环境相同配置可正常运行:

正常场景

  • ✅ 开发、预发布环境所有操作(含插入)正常
  • ✅ 生产环境查询、搜索、删除、更新操作正常
  • ✅ 生产环境通过curl直接插入文档成功
  • ✅ 所有环境products索引均存在且可访问

失败场景

  • ❌ 仅生产环境通过PHP客户端插入文档失败

环境信息

  • 框架:Laravel(Docker部署)
  • OpenSearch PHP客户端:opensearch-project/opensearch-php
  • 生产OpenSearch地址:https://opensearch.prd.company.com
  • 预发布OpenSearch地址:https://opensearch.stg.company.com:443(正常运行)

代码示例

public function set(string $product_id, array $product_data): array
{
    $request = [
        'index' => 'products',
        'id' => $product_id, // e.g 'product_123'
        'body' => $product_data, // e.g ['name' => 'Product Name', 'price' => 100]
    ];

    return $this->client->index($request); // 404错误触发点
}

复现步骤

生产环境curl命令可成功执行:

curl -X POST "https://opensearch.prd.company.com/products/_doc/HELLO-PC" \
  -H "Content-Type: application/json" \
  -u admin:*** \
  -d '{"title": "Hello PC", "price": 999.99, "category": "Gaming PCs"}'

但上述PHP客户端方法抛出404错误。

错误堆栈

OpenSearch\Exception\NotFoundHttpException: 404 NotFoundHttpException
#0 /vendor/opensearch-project/opensearch-php/src/OpenSearch/HttpTransport.php(56): 
   OpenSearch\Exception\HttpExceptionFactory::create(404, '')
#1 /vendor/opensearch-project/opensearch-php/src/OpenSearch/Client.php(2182): 
   OpenSearch\HttpTransport->sendRequest('POST', '/products/_doc/...', Array, Array, Array)
#2 /vendor/opensearch-project/opensearch-php/src/OpenSearch/Client.php(1114): 
   OpenSearch\Client->performRequest(Object(OpenSearch\Endpoints\Index))
#3 /app/Services/ProductStore/ProductStoreClient.php(65): 
   OpenSearch\Client->index(Array)

可能原因与解决方案

1. 客户端与服务端版本不兼容

不同版本的OpenSearch客户端和服务端,index()方法生成的请求路径可能存在差异。例如旧版客户端(1.x)可能生成/products/{id}路径,而新版服务端(2.x)要求必须带/_doc后缀(即/products/_doc/{id}),导致路径不存在。

验证与解决:

  • 查看生产环境OpenSearch版本:
    curl -X GET "https://opensearch.prd.company.com/"
    
  • 查看客户端版本(composer.lock中opensearch-project/opensearch-php的版本),确保客户端与服务端版本匹配(如服务端2.x则客户端用2.x分支)。
  • 若版本不兼容,升级/降级客户端至对应兼容版本。

2. 生产环境反向代理/网关改写请求路径

生产环境的反向代理(如Nginx)或API网关可能对POST请求的路径做了特殊处理,比如移除了/_doc后缀,而PHP客户端生成的路径不符合网关规则,但curl的路径刚好适配。

验证与解决:

  • 开启客户端调试模式,查看实际发送的请求URL:
    $client = \OpenSearch\ClientBuilder::create()
        ->setHosts(config('opensearch.hosts'))
        ->setDebug(true) // 开启调试
        ->build();
    
    调试日志会打印完整请求URL,对比curl的路径是否一致。
  • 若路径不一致,可手动指定doc_type参数(针对旧版客户端),或修改网关规则适配客户端路径。

3. 索引别名/路径映射配置差异

生产环境的products可能是一个别名而非实际索引,客户端的index()方法在处理别名时存在逻辑差异;或者生产环境要求特定的文档类型(OpenSearch 2.x已移除类型,但旧版本可能保留)。

验证与解决:

  • 检查生产环境products是否为别名:
    curl -X GET "https://opensearch.prd.company.com/_aliases" | grep products
    
  • 若为别名,尝试直接使用实际索引名称测试插入;或在客户端请求中显式指定doc_type为_doc:
    $request = [
        'index' => 'products',
        'id' => $product_id,
        'doc_type' => '_doc', // 显式指定文档类型
        'body' => $product_data,
    ];
    

4. 权限伪装的404错误

部分网关会将权限不足错误伪装为404,虽然curl用admin账号成功,但客户端可能使用了权限不足的账号。

验证与解决:

  • 临时将客户端切换为admin账号测试,若插入成功,则说明原账号缺少插入权限,需在OpenSearch中为该账号分配write权限。

内容的提问来源于stack exchange,提问作者Zabs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 22:54:49