如何在Laravel队列中容纳Amazon FIFO SQS?

时间:2016-11-22 04:47:44

标签: php laravel amazon-web-services amazon-sqs

亚马逊宣布了他们的new FIFO SQS service,我想在Laravel Queue中使用它来解决一些并发问题。

我创建了几个新队列并更改了配置。但是,我收到MissingParameter错误,说明

The request must contain the parameter MessageGroupId.

所以我修改了文件vendor/laravel/framework/src/Illuminate/Queue/SqsQueue.php

public function pushRaw($payload, $queue = null, array $options = [])
{
    $response = $this->sqs->sendMessage(['QueueUrl' => $this->getQueue($queue), 'MessageBody' => $payload,
        'MessageGroupId' => env('APP_ENV', getenv('APP_ENV'))]);

    return $response->get('MessageId');
}

public function later($delay, $job, $data = '', $queue = null)
{
    $payload = $this->createPayload($job, $data);

    $delay = $this->getSeconds($delay);

    return $this->sqs->sendMessage([
        'QueueUrl' => $this->getQueue($queue), 'MessageBody' => $payload, 'DelaySeconds' => $delay,
        'MessageGroupId' => env('APP_ENV', getenv('APP_ENV'))
    ])->get('MessageId');
}

我使用APP_ENV作为群组ID(它是一个单一的消息队列,所以实际上它并不重要。我只想要一切都是FIFO)。

但我仍然收到相同的错误消息。我该怎么办呢?任何帮助将不胜感激。

(顺便说一句,SDK定义在哪里sendMessage?我可以找到它的存根,但我没有找到详细的实现)

3 个答案:

答案 0 :(得分:16)

我想指出那些可能偶然遇到同一问题的人,尽管编辑SqsQueue.php有效,但很容易被composer installcomposer update重置。另一种方法是为SQS FIFO实现一个新的Illuminate\Queue\Connectors\ConnectorInterface,然后将其添加到Laravel的队列管理器中。

我的方法如下:

  1. 创建一个扩展SqsFifoQueue但支持SQS FIFO的新Illuminate\Queue\SqsQueue类。
  2. 创建一个新的SqsFifoConnector类,扩展Illuminate\Queue\Connectors\SqsConnector,使用SqsFifoQueue建立连接。
  3. 创建一个新的SqsFifoServiceProvider,将SqsFifoConnector注册到Laravel的队列管理器。
  4. SqsFifoServiceProvider添加到您的config/app.php
  5. 更新config/queue.php以使用新的SQS FIFO队列驱动程序。
  6. 示例:

    1. 创建一个扩展SqsFifoQueue但支持SQS FIFO的新Illuminate\Queue\SqsQueue类。

      <?php
      
      class SqsFifoQueue extends \Illuminate\Queue\SqsQueue
      {
          public function pushRaw($payload, $queue = null, array $options = [])
          {
              $response = $this->sqs->sendMessage([
                  'QueueUrl' => $this->getQueue($queue),
                  'MessageBody' => $payload,
                  'MessageGroupId' => uniqid(),
                  'MessageDeduplicationId' => uniqid(),
              ]);
      
              return $response->get('MessageId');
          }
      }
      
    2. 创建一个新的SqsFifoConnector类,扩展Illuminate\Queue\Connectors\SqsConnector,使用SqsFifoQueue建立连接。

      <?php
      
      use Aws\Sqs\SqsClient;
      use Illuminate\Support\Arr;
      
      class SqsFifoConnector extends \Illuminate\Queue\Connectors\SqsConnector
      {
          public function connect(array $config)
          {
              $config = $this->getDefaultConfiguration($config);
      
              if ($config['key'] && $config['secret']) {
                  $config['credentials'] = Arr::only($config, ['key', 'secret']);
              }
      
              return new SqsFifoQueue(
                  new SqsClient($config), $config['queue'], Arr::get($config, 'prefix', '')
              );
          }
      }
      
    3. 创建一个新的SqsFifoServiceProvider,将SqsFifoConnector注册到Laravel的队列管理器。

      <?php
      
      class SqsFifoServiceProvider extends \Illuminate\Support\ServiceProvider
      {
          public function register()
          {
              $this->app->afterResolving('queue', function ($manager) {
                  $manager->addConnector('sqsfifo', function () {
                      return new SqsFifoConnector;
                  });
              });
          }
      }
      
    4. SqsFifoServiceProvider添加到config/app.php

      <?php
      
      return [
          'providers'     => [
              ...
              SqsFifoServiceProvider::class,
          ],
      ];
      
    5. 更新config/queue.php以使用新的SQS FIFO队列驱动程序。

      <?php
      
      return [
      
          'default' => 'sqsfifo',
      
          'connections' => [
              'sqsfifo' => [
                  'driver' => 'sqsfifo',
                  'key'    => 'my_key'
                  'secret' => 'my_secret',
                  'queue'  => 'my_queue_url',
                  'region' => 'my_sqs_region',
              ],
          ],
      ];
      
    6. 然后你的队列现在应该支持SQS FIFO队列。

      无耻插件:在执行上述步骤时,我创建了一个laravel-sqs-fifo作曲家包,以便在https://github.com/maqe/laravel-sqs-fifo处理此问题。

答案 1 :(得分:2)

FIFO消息的工作方式与标准AWS SQS队列不同。

您需要一个单独的驱动程序来处理FIFO队列。

我不得不面对同样的情况,下面的包裹是救生员。

https://packagist.org/packages/shiftonelabs/laravel-sqs-fifo-queue

queue.php

'sqs-fifo' => [
            'driver' => 'sqs-fifo',
            'key' => env('SQS_KEY'),
            'secret' => env('SQS_SECRET'),
            'prefix' => env('SQS_PREFIX'),
            'queue' => env('SQS_QUEUE'),
            'region' => env('SQS_REGION'),
            'group' => 'default',
            'deduplicator' => 'unique',
        ],

然后

dispatch(new TestJob([]))->onQueue('My_Mail_Queue.fifo');

注意: 您需要在.env

中指定要在应用程序中使用的默认队列名称
SQS_QUEUE=My_Default_queue.fifo

此外,您需要在侦听器中指定要在应用程序中使用的所有队列名称。 (如果您为整个应用程序使用相同的队列名称,则无需在侦听器中指定队列名称)

php artisan queue:listen --queue=My_Default_queue.fifo,My_Mail_Queue.fifo,My_Message_Queue.fifo

答案 2 :(得分:0)

open class UnitFlowRate : Dimension { open override static func baseUnit() -> UnitFlowRate { return self.metricTonsPerHour } static let shortTonsPerHour = UnitFlowRate(symbol: NSLocalizedString("stph", comment: "short tons per hour"), converter: UnitConverterLinear(coefficient: 0.5)) static let metricTonsPerHour = UnitFlowRate(symbol: NSLocalizedString("mtph", comment: "metric tons per hour"), converter: UnitConverterLinear(coefficient: 1)) } 外,它还需要MessageGroupId或启用基于内容的重复数据删除。