【问题标题】:Check if Azure Queue exists using REST proxy (PHP)使用 REST 代理 (PHP) 检查 Azure 队列是否存在
【发布时间】:2014-02-27 13:40:12
【问题描述】:

我正在尝试使用 Windows Azure SDK for PHP 提供的 REST 代理与 Azure 队列交互。虽然有很多代码示例 here,但我想检查是否存在队列,以便在必要时创建它,然后再向其中添加消息。

try {
  // setup connection string for accessing queue storage
  $connectionString = 'DefaultEndpointsProtocol=' . PROTOCOL . ';AccountName=' . ACCOUNT_NAME . ';AccountKey=' . ACCOUNT_KEY;

  // create queue REST proxy
  $queueRestProxy = ServicesBuilder::getInstance()->createQueueService($connectionString);

  // create message
  $queueRestProxy->createMessage(QUEUE_NAME, 'Hello World!');

} catch(ServiceException $e){
  // Handle exception based on error codes and messages.
  // Error codes and messages are here: 
  // http://msdn.microsoft.com/en-us/library/windowsazure/dd179446.aspx
  $code = $e->getCode();
  $error_message = $e->getMessage();
  echo $code.": ".$error_message."<br />";
}

创建队列就这么简单...

$queueRestProxy->createQueue(QUEUE_NAME);

我应该在创建消息之前简单地包含队列创建代码,还是有更有效的方法来确定队列是否存在,然后再与它交互?

【问题讨论】:

    标签: php azure azure-storage azure-storage-queues


    【解决方案1】:

    通常在其他 Windows Azure SDK 中,我见过像 createQueueIfNotExists 这样的方法,我很惊讶 PHP SDK 中缺少这种方法。基本上这个函数的工作方式是它试图创建一个队列。如果存储中存在同名队列,存储服务会抛出Conflict (409) 错误。

    由于没有此功能,您可以执行相同的操作,即尝试在其自己的 try/catch 块中创建队列并检查错误代码。如果错误代码是 409,则继续,否则重新抛出异常。类似于下面的代码:

    try {
      // setup connection string for accessing queue storage
      $connectionString = 'DefaultEndpointsProtocol=' . PROTOCOL . ';AccountName=' . ACCOUNT_NAME . ';AccountKey=' . ACCOUNT_KEY;
        // create queue REST proxy
            $queueRestProxy = ServicesBuilder::getInstance()->createQueueService($connectionString);
      try {
        // now try to create the queue.
    $queueRestProxy->createQueue(QUEUE_NAME);
      } catch(ServiceException $e){
        $code = $e->getCode();
        //Now check if the $code is 409 - Conflict. If the error code is indeed 409, you continue otherwise throw the error
      }
      // create message
      $queueRestProxy->createMessage(QUEUE_NAME, 'Hello World!');
    
    } catch(ServiceException $e){
      // Handle exception based on error codes and messages.
      // Error codes and messages are here: 
      // http://msdn.microsoft.com/en-us/library/windowsazure/dd179446.aspx
      $code = $e->getCode();
      $error_message = $e->getMessage();
      echo $code.": ".$error_message."<br />";
    }
    

    附:我没有尝试执行代码,所以它可能会抛出错误。这只是给你一个想法。

    【讨论】:

    • @Guarav - 感谢您的回复。经过一些测试,对 createQueue(QUEUE_NAME) 的多次连续调用似乎不会导致抛出 ServiceException,因此 Azure 内部似乎默默地处理了这个问题。也许这就是他们没有在 SDK 中发布 createQueueIfNotExists 和 queueExists 方法的原因。
    • 我不这么认为。此外,所有其他 SDK 都具有此功能。 .Net 请参见此处:msdn.microsoft.com/en-us/library/windowsazure/…。所有的 SDK 都是 REST API 的封装,所以我认为这不是原因。
    • 诚然,我的观察与创建队列 REST API 页面 (msdn.microsoft.com/en-us/library/windowsazure/dd179342.aspx) 上的“备注”部分不一致,这与您的回答一致,即如果队列存在非匹配元数据,如果队列存在匹配元数据,则返回 204。但是,我没有看到这些响应代码的真实性,因为没有引发异常。
    • 有趣的是,有一个名为“testCreateQueueWithExistingQueue”的单元测试调用了两次 createQueue($queueName) 并期望只创建 1 个队列(没有任何异常处理) - 请参阅 github.com/WindowsAzure/azure-sdk-for-php/blob/…
    • 我明白了。感谢您提供文档链接,您是对的(今天学到了一些新东西:))。因此,如果您尝试创建一个名称与现有队列匹配的队列并且元数据没有不同,则返回的状态代码为 204,这并不是真正的异常情况,因此您不会收到错误消息。我认为任何时候存储服务发送一个大于或等于 400 的状态码,你都会得到服务异常。否则不会引发异常。
    【解决方案2】:

    为了完整起见,我在下面发布了一个答案,以便人们一眼就能看到答案。

    我是否应该在创建队列之前简单地包含队列创建代码? 消息或是否有更有效的方法来确定是否 队列在与之交互之前就存在?

    有两种方法可以解决这个问题...

    1. 在创建消息之前包含createQueue 语句,但按照Guarav Mantri's answer 的指示将该语句包装在try-catch 块中,即忽略409 错误,但针对任何其他类型的错误抛出异常。

      有关信息,当您在创建消息之前包含 createQueue 语句时...

      • 如果同名队列已经存在并且元数据 与现有队列关联与传递给 createQueue 语句则不会创建队列并且 队列 REST 代理将在内部接收 204(无内容)状态代码,但这 响应代码不提供给程序员。所以, 本质上,createQueue 语句不会导致 在这种情况下会引发错误/异常。

      • 如果同名队列已经存在并且元数据 与现有队列关联与传递的相同 到createQueue 语句,则不会创建队列,并且 队列 REST 代理将收到 409(冲突)状态代码,并将引发 允许程序员访问此响应代码和关联的QueueAlreadyExists 消息的异常。

      来源:Create Queue (REST API) - 见备注部分

    2. 创建一个queueExists 函数并调用它来决定是否需要创建队列。这是实现此类功能的一种方法...

      public function queueExists($queueRestProxy, $queueName) {
        $result = FALSE;
        $listQueuesResult = $queueRestProxy->listQueues();
        $queues = $listQueuesResult->getQueues();
        foreach($queues as $queue) {
          if ($queue->getName() === $queueName) {
            $result = TRUE;
            break;
          }
        }
        return $result;        
      }
      

    希望这对某人有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多