O RabbitMQ não óbvio no Yii2 ou por que o RabbitMQ grava em todas as filas de uma só vez


Quero compartilhar o problema prático de configurar o broker de fila RabbitMQ no Yii2. Eu aviso ao leitor que não tenho uma opinião de especialista sobre como trabalhar com esse broker de filas, no entanto, realmente quero preencher as lacunas na documentação do Yii2 e corrigir o resultado do meu próprio tormento. Portanto, se você já encontrou um problema em que as mensagens são enviadas para todas as filas que estão no servidor de filas, você concorda que esse é um problema e não entende por que isso acontece, então peço um gato.

Por que você pode encontrar esse comportamento? Por exemplo, se você, como eu, não trabalhou com RabbitMQ antes, mas trabalhou com Gearman, por exemplo. O próprio Gearman, tão simples quanto uma ferrovia ( emprestado de um conhecido e respeitado personagem da Internet ). Você cria uma fila com um determinado nome, coloca os dados lá. O trabalhador lê da fila com o mesmo nome. Tudo é simples. Agora é hora de usar a tecnologia da moda, sem entender por que você escolhe o RabbitMQ. Então você está feliz que o Yii2 tenha uma abstração pronta para muitos corretores de filas populares. A documentação escassa informa a configuração padrão para começar tudo:

return [ 'bootstrap' => [ 'queue', // The component registers its own console commands ], 'components' => [ 'queue' => [ 'class' => \yii\queue\amqp_interop\Queue::class, 'port' => 5672, 'user' => 'guest', 'password' => 'guest', 'queueName' => 'queue', 'driver' => yii\queue\amqp_interop\Queue::ENQUEUE_AMQP_LIB, // or 'dsn' => 'amqp://guest:guest@localhost:5672/%2F', // or, same as above 'dsn' => 'amqp:', ], ], ]; 

Parece que tudo é incrivelmente simples, aqui está a linha familiar com o nome da fila , copie e cole, corrija e execute - funciona! Criamos filas para outros componentes do sistema. Paralelamente ao que nosso php pode. Confirme, empurre satisfeito que colocamos a tarefa no controle de qualidade e vamos ler um habr ( no intervalo do almoço ).

Aqui, o mais interessante, o controle de qualidade no bate-papo nos interrompe e diz que algo estranho está acontecendo. Por alguma razão, os dados que os trabalhadores (clientes) gravam são duplicados. O que o que Não pode ser assim. Vamos verificar os logs. Vimos que a mensagem está sendo gravada na fila, com a qual a fila está selecionada corretamente, o hash jobId é recebido. Não, não, não temos erros. Estamos escrevendo QAs satisfeitos, verifique novamente, não pode ser, estamos indo bem.

Literalmente, após meia hora, fomos distraídos novamente, o erro foi repetido e, em seguida, uma notificação caiu no sabão - a tarefa foi transferida de volta ao trabalho. Bem, eu sou um programador, agora vamos descobrir. O RabbitMQ, ao contrário do Gearman, possui uma interface web na qual há muitas informações sobre o servidor. Esse milagre é assim:



Jogamos mais algumas mensagens na fila, vemos no webmord que nossas mensagens chegam e são processadas pelo trabalhador. Uma aparência casual observa que, quando jogamos uma mensagem na fila, o gráfico "Taxas de mensagens" entra em todas as filas.



Verificamos a configuração centenas de vezes e relemos a escassa documentação do Yii. Fizemos tudo certo. Vamos ler a documentação no site do coelho. Depois de algumas dezenas de minutos vagando no escuro, deparamos com um tutorial . Imediatamente após o primeiro parágrafo, nos familiarizamos com o motivo de nossos mal-entendidos - trocas. Não vou repetir a documentação muito brevemente.

No RabbitMQ, não escrevemos uma mensagem para a fila, escrevemos para troca, um tipo de proxy que recebe nossas mensagens em uma extremidade e se comunica com as filas no servidor na outra extremidade. Está em seu poder decidir em qual fila colocar nossos dados. Curiosamente, não há uma única linha sobre isso na documentação do Yii. À primeira vista, não está claro como configurar o Exchange, mergulhamos no interior e no fornecedor de arquivos / yiisoft / yii2-queue / src / drivers / amqp_interop / Queue.php: 176 encontramos uma propriedade que pode ser vista. Aqui devo dizer que existem muitos drivers para o RabbitMQ; no meu caso, o enfileiramento / amqp-lib é usado . Definimos exchangeName , test, nada muda. Bem, somos como um verdadeiro engenheiro russo, primeiro tentamos e depois pensamos em ler a documentação novamente. Lemos com cuidado novamente, depois vamos para a face da web do coelho e vemos o seguinte:



Várias de nossas filas estão associadas à mesma troca. Bingo! Aqui está a razão, um "mas", eu não os vinculei. Entramos novamente no intestino do motorista, encontramos a linha 392 do método setupBroker

 $this->context->bind(new AmqpBind($queue, $topic)); 

Esta é uma ligação não gerenciada.

E assim, sem pensar muito, chegamos à conclusão de que para cada fila uma troca deve ser declarada, a conexão estará correta e uma troca terá apenas uma fila conectada. Dessa forma, obtemos um comportamento semelhante ao Gearman. A propósito, a documentação descreve em detalhes por que a troca foi realizada e, pelo que entendi, uma das razões é a capacidade de vincular várias filas à troca. Mas não inventei um caso como esse quando necessário, pessoal escrevem nos comentários. E escreva, você encontrou a situação descrita acima ou estou fazendo tudo errado?

Source: https://habr.com/ru/post/pt439080/


All Articles