Очереди сообщений - неотъемлемая часть системы, находящейся под высокой нагрузкой. Они защищают приложения от разрушительного воздействия нагрузки, а также помогают легко масштабировать приложения.

Если система состоит из множества экземпляров приложений и / или некоторых устройств, это означает, что у вас также есть много производителей журналов. Таким образом, вы должны масштабировать систему ведения журнала по мере масштабирования приложения. В противном случае на механизм регистрации может повлиять внешняя нагрузка, он может быть безответственным и легко вывести из строя всю систему.

Вы также можете масштабировать системы регистрации, используя очереди сообщений. Сегодня я попытаюсь объяснить, как настроить RabbitMQ и Graylog для отправки журналов в Graylog из приложения Symfony через RabbitMQ.

Установка зависимостей Composer:
Установите RabbitMQBundle для доступа к экземпляру RabbitMQ из приложения.

$ composer require php-amqplib/rabbitmq-bundle

Определите соединение RabbitMQ с config.yml

# app/config/config.yml
...
old_sound_rabbit_mq:
    connections:
        logging:
            host: '%rabbitmq_host%'
            user: '%rabbitmq_user%'
            password: '%rabbitmq_password%'
            vhost: '%rabbitmq_logging_vhost%'
    producers:
        logging:
            connection: logging
            exchange_options:
                name: logging
                type: fanout

Определите учетные данные для подключения RabbitMQ в parameters.yml, которые описаны в config.yml

# app/config/parameters.yml
parameters:
 ...
 rabbitmq_host: <your_rabbitmq_host_address>
 rabbitmq_user: <your_rabbitmq_user>
 rabbitmq_password: <your_rabbitmq_password>
 rabbitmq_logging_vhost: logging

Определите новый сервис для канала RabbitMQ, который будет использоваться monolog.

# app/config/services.yml
services:
...
    monolog_mq_channel:
        class: PhpAmqpLib\Channel\AMQPChannel
        arguments:
          - "@old_sound_rabbit_mq.connection.logging"

Определите обработчик монолога в файле конфигурации Symfony, как показано ниже. Для демонстрации мы будем использовать config_dev.yml Вы можете определить обработчики специально для каждой среды.

# app/config/config_dev.yml
monolog:
    handlers:
        console:
            type: amqp
            exchange: monolog_mq_channel
            exchange_name: logging
            level: warning

Теперь приложение готово к отправке логов в RabbitMQ. Давайте настроим экземпляр сервера RabbitMQ для приема сообщений.

Настроить RabbitMQ

В этом примере я предпочел создать конкретный виртуальный сервер, чтобы отделить приложение и журнал, связанные с зависимостями RabbitMQ. Вы можете проигнорировать этот шаг, если планируете использовать отдельный экземпляр RabbitMQ.

$ rabbitmqctl add_vhost logging
$ rabbitmqctl set_permissions -p logging guest “.*” “.*” “.*”

Создайте новый обмен на RabbitMQ с именем, которое вы указали в конфигурации как производитель.

$ ./bin/console rabbitmq:setup-fabric

Теперь сервер RabbitMQ готов получать логи от приложения.

Настройте производитель журналов для демонстрации

Вы можете просто создать команду Symfony, как показано ниже, чтобы создать несколько записей журнала в очереди сообщений.

<?php
namespace AppBundle\Command;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class LoggingTestCommand extends ContainerAwareCommand
{
    protected function configure()
    {
        $this->setName('logging:test')
            ->setDescription('Tester command for sending log over');
    }
protected function execute(InputInterface $input, OutputInterface $output)
    {
        /** @var LoggerInterface $logger */
        $logger = $this->getContainer()->get('logger');
        $output->writeln('Test messages are sending to message queue now. Please press CTRL+C to break this process.');
        while(true) {
            $logger->error('Some error occurred while doing sometihng.', [
                'some_value'    => 'ABC',
                'another_value' => 1532,
            ]);
            usleep(500);
        }
    }
}

Демо

Вызовите следующую команду, чтобы создать несколько журналов на сервере RabbitMQ.

$ ./bin/console logging:test

Как видно из следующего рисунка; приложение запускает отправку логов на сервер RabbitMQ.

Настроить Graylog

Войдите в свой Graylog как администратор и перейдите в раздел Inputs из меню System.

Выберите «GELF AMQP» из раскрывающегося списка в верхней части страницы и нажмите кнопку Launch new input (зеленая кнопка рядом с раскрывающимся списком).

Заполните поля ввода в открывшемся всплывающем окне следующими значениями:

Заголовок: ошибки
Общий: (установлен) (это означает, что все узлы в вашем кластере серого журнала будут использовать этот ввод в качестве источника)
Exchange: ведение журнала
Виртуальный хост брокера: ведение журнала
Очередь: testapp-logs
Имя хоста брокера: (Ваш адрес хоста rabbitmq)
Разрешить регулирование этого ввода: (отмечено) (Этот параметр обычно используется при чтении журналов из файла или очереди сообщений.)
Привязать к обмену: (отмечено) (это означает, что graylog автоматически привяжет очередь testapp-logs к вашему обмену.)
Ключ маршрутизации: #

Как видите, журналы начинают поступать из RabbitMQ в Graylog.

Вы можете найти этот пример и все настройки Graylog / RabbitMQ в следующем репозитории.



Спасибо за прочтение!