升级AWS SDK for PHP至V3后调用本地SQS接口JSON解析错误求助
我们使用AWS SDK for PHP调用本地SQS端点发送消息,本地同时运行Lambda函数。将SDK从V2升级到V3并完成代码适配后,始终遇到错误:Unable to parse error information from response - Error parsing JSON: Syntax error。尝试过更换不同版本的AWS SDK V3、开启客户端调试选项都未获取有效排查信息,回退到V2版本可正常运行,但因业务需要必须使用V3的功能,无法回退。
当前代码
客户端初始化代码
$this->client = new SqsClient([ 'credentials' => [ 'key' => $this->key, 'secret' => $this->secret ], 'region' => $this->region, 'endpoint' => $this->endpoint, 'version' => 'latest', ]);
发送消息函数
public function push($queue, $message) { try { $urlResult = $this->client->getQueueUrl([ 'QueueName' => $queue ]); $result = $this->client->sendMessage([ 'QueueUrl' => $urlResult['QueueUrl'], 'MessageBody' => json_encode($message), ]); return $result; } catch (\Exception $e) { throw $e; return [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]; } }
排查与解决方案
1. 升级本地SQS服务版本
AWS SDK V3对API响应格式的校验比V2更严格,若使用的是LocalStack这类本地模拟服务,旧版本可能存在V3兼容性问题,导致返回的响应不符合SDK预期的JSON格式。建议将本地SQS服务升级到最新稳定版后重试。
2. 显式指定签名版本
V3默认使用v4签名,部分本地SQS服务可能需要显式声明签名版本才能正常交互。在客户端初始化时添加signature_version参数:
$this->client = new SqsClient([ 'credentials' => [ 'key' => $this->key, 'secret' => $this->secret ], 'region' => $this->region, 'endpoint' => $this->endpoint, 'version' => 'latest', 'signature_version' => 'v4', ]);
3. 禁用本地环境的SSL验证
如果本地SQS端点使用HTTP协议而非HTTPS,SDK V3可能默认尝试SSL证书验证,导致响应异常。在客户端配置中添加verify参数禁用验证(仅用于开发环境):
$this->client = new SqsClient([ 'credentials' => [ 'key' => $this->key, 'secret' => $this->secret ], 'region' => $this->region, 'endpoint' => $this->endpoint, 'version' => 'latest', 'verify' => false, ]);
4. 开启详细日志查看原始响应
通过SDK的日志功能查看本地SQS返回的原始响应,确认是否返回了非JSON内容或格式错误的JSON。配置日志示例:
use Psr\Log\LogLevel; $this->client = new SqsClient([ 'credentials' => [ 'key' => $this->key, 'secret' => $this->secret ], 'region' => $this->region, 'endpoint' => $this->endpoint, 'version' => 'latest', 'logger' => new \Monolog\Logger('aws-sdk'), // 替换为你项目中使用的日志实例 'log_level' => LogLevel::DEBUG, ]);
通过日志中的原始响应内容,可直接定位JSON解析失败的具体原因。
5. 规范响应结果的取值方式
SDK V3的响应是Aws\Result对象,虽然支持数组式访问,但使用get()方法取值更稳妥,避免潜在的类型转换问题:
public function push($queue, $message) { try { $urlResult = $this->client->getQueueUrl([ 'QueueName' => $queue ]); $result = $this->client->sendMessage([ 'QueueUrl' => $urlResult->get('QueueUrl'), // 使用get()方法取值 'MessageBody' => json_encode($message), ]); return $result; } catch (\Exception $e) { throw $e; return [ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]; } }
内容的提问来源于stack exchange,提问作者Francisco Mauri

