PHP Azure SDK服务总线返回格式错误的响应


PHP Azure SDK Service Bus returns Malformed Response

我正在开发某种跟踪记录器,它将日志消息请求推送到服务总线上的队列中,稍后由一个工作角色拾取,该角色将把它们插入表存储中。当在我的机器上运行时,它运行得很好(因为我是唯一一个使用它的人),但一旦我把它放在服务器上进行测试,它就会产生以下错误:

HTTP_Request2_MessageException: Malformed response: in D:'home'site'wwwroot'vendor'pear-pear.php.net'HTTP_Request2'HTTP'Request2'Adapter'Socket.php on line 1013
0   HTTP_Request2_Response->__construct('', true, Object(Net_URL2)) D:'home'site'wwwroot'vendor'pear-pear.php.net'HTTP_Request2'HTTP'Request2'Adapter'Socket.php:1013
1   HTTP_Request2_Adapter_Socket->readResponse()    D:'home'site'wwwroot'vendor'pear-pear.php.net'HTTP_Request2'HTTP'Request2'Adapter'Socket.php:139
2   HTTP_Request2_Adapter_Socket->sendRequest(Object(HTTP_Request2))    D:'home'site'wwwroot'vendor'pear-pear.php.net'HTTP_Request2'HTTP'Request2.php:939
3   HTTP_Request2->send()   D:'home'site'wwwroot'vendor'microsoft'windowsazure'WindowsAzure'Common'Internal'Http'HttpClient.php:262
4   WindowsAzure'Common'Internal'Http'HttpClient->send(Array, Object(WindowsAzure'Common'Internal'Http'Url))    D:'home'site'wwwroot'vendor'microsoft'windowsazure'WindowsAzure'Common'Internal'RestProxy.php:141
5   WindowsAzure'Common'Internal'RestProxy->sendContext(Object(WindowsAzure'Common'Internal'Http'HttpCallContext))  D:'home'site'wwwroot'vendor'microsoft'windowsazure'WindowsAzure'Common'Internal'ServiceRestProxy.php:86
6   WindowsAzure'Common'Internal'ServiceRestProxy->sendContext(Object(WindowsAzure'Common'Internal'Http'HttpCallContext))   D:'home'site'wwwroot'vendor'microsoft'windowsazure'WindowsAzure'ServiceBus'ServiceBusRestProxy.php:139
7   WindowsAzure'ServiceBus'ServiceBusRestProxy->sendMessage('<queuename>/mes…', Object(WindowsAzure'ServiceBus'Models'BrokeredMessage))    D:'home'site'wwwroot'vendor'microsoft'windowsazure'WindowsAzure'ServiceBus'ServiceBusRestProxy.php:155
⋮

我以前看到过描述类似问题的帖子;即:

  • Windows Azure PHP队列REST代理限制(堆栈溢出)
  • HTTPS上的操作无法正常工作(GitHub)

这意味着这是关于PHP Azure存储库的一个已知问题,其中允许的HTTPS连接数量有限。在更改需求之前,我直接访问表存储,遇到了同样的问题,并按照第一个链接所描述的方式进行了修复。

问题是,与表存储(等)连接字符串端点不同,连接字符串中的服务总线端点必须是"HTTPS"。尝试将其与"HTTP"一起使用将返回一个400错误的请求错误。

我想知道是否有人对潜在的变通方法有任何想法。如有任何建议,我们将不胜感激。

谢谢!

编辑(根据Gary Liu的评论):

这是我用来向队列添加项目的代码:

private function logToAzureSB($source, $msg, $severity, $machine)
{
    // Gather all relevant information
    $msgInfo = array(
        "Severity" => $severity,
        "Message" => $msg,
        "Machine" => $machine,
        "Source" => $source
        );
    // Encode it to a JSON string, and add it to a Brokered message.
    $encoded = json_encode($msgInfo);
    $message = new BrokeredMessage($encoded);
    $message->setContentType("application/json");
    // Attempt to push the message onto the Queue
    try
    {
        $this->sbRestProxy->sendQueueMessage($this->azureQueueName, $message);
    }
    catch(ServiceException $e)
    {
        throw new 'DatabaseException($e->getMessage, $e->getCode, $e->getPrevious);
    }
}

这里,$this->sbRestProxy是一个服务总线REST代理,在日志类初始化时设置。

在事物的接收端,以下是Worker角色方面的代码:

public override void Run()
{
     // Initiates the message pump and callback is invoked for each message that is received, calling close on the client will stop the pump.
     Client.OnMessage((receivedMessage) =>
     {
         try
         {
             // Pull the Message from the recieved object.
             Stream stream = receivedMessage.GetBody<Stream>();
             StreamReader reader = new StreamReader(stream);
             string message = reader.ReadToEnd();
             LoggingMessage mMsg = JsonConvert.DeserializeObject<LoggingMessage>(message);
              // Create an entry with the information given.
              LogEntry entry = new LogEntry(mMsg);
              // Set the Logger to the appropriate table store, and insert the entry into the table.
              Logger.InsertIntoLog(entry, mMsg.Service);
          }
          catch
          {
              // Handle any message processing specific exceptions here
          }
      });
      CompletedEvent.WaitOne();
}

其中Logging Message是一个简单的对象,它基本上包含与PHP中记录的Message相同的字段(用于JSON反序列化),LogEntry是一个TableEntity,它也包含这些字段,Logger是在工作角色的OnStart方法期间设置的表存储记录器的实例。

这是Windows Azure PHP的一个已知问题,很久没有人研究过,也没有修复过。在我发布这篇文章到现在的这段时间里,我们最终编写了一个单独的API web服务用于日志记录,并让我们的PHP代码通过cURL向其发送JSON字符串,这作为一种临时解决方案非常有效。我们现在正在脱离PHP,所以无论如何,这在更长的时间内都不会是一个问题。