Pull to refresh

Размазываем PHP

Reading time 3 min
Views 29K
image

Настанет день, и ты поймешь, что одного потока в PHP тебе мало.

Сначала ты оптимизируешь код, потом пытаешься изменить сознание на асинхронный реакт, но весь PHP мир не хочет понимать такое стремление. Смотришь на phthreads, но после java concurrency чувствуешь, что тебя где-то “обманули”. А когда ты задумаешь покинуть процесс и начнешь захлебываться в форках exec’ах и сигналах, ты поймешь, что дальше погружаться нельзя. И, наконец, всплыв из всего этого, ты поплывешь к острову MOM (message-oriented middleware).

Оооо, а каких тут продавцов кирби только нет: RabbitMQ, ActiveMQ, Kafka, Kestrel и даже Redis pub/sub’ом подбарыживает. И у всех все хорошо: все самое лучшее, быстрое, безотказное. Но есть небольшая беда — шаг в сторону и, привет, теперь ты в числе толпы нытиков на stackoverflow в поисках воркэраундов и странных схем. И это будет продолжаться пока ты не найдешь ZeroMQ.

А что это? ZeroMQ — высокопроизводительная асинхронная месседж-ориентированная библиотека направленная на использование в масштабируемых распределенных или параллельных приложениях. Но в отличии от других месседж-ориентированных мидлваре она безброкерная и работает без сервера, как такового.



И что же тут предлагают тогда? А предлагают эти ребята набор сокетов на стероидах оптимизированных под основные месседж паттерны и использовать мы их можем как хотим. С их помощью можем построить сеть с любой топологией и сложностью.

Еще у них есть своя сектанская дока http://zguide.zeromq.org/page:all. Хорошо вправляет мозги в нужном направлении независимо от того, будешь использовать 0mq или нет, правда, если можешь в многопоточное программирование, можно частично пролистывать.

В сухом остатке:

  • Набор стероидных сокетов
  • Чертовски быстрые
  • Работа через IPC,TCP, multicast, inproc
  • Асинхронные
  • Легкий старт
  • Байндинги для овер 40 языков программирования


Звучит все это очень круто! Хватит теорий идем на www.gliffy.com и яростно архитектурим систему. А хотим мы следующее:

image

  • Auth + task generator
    Отвечает за авторизацию на сервере и раздает нон-стоп задачи на парсинг.
  • Parse worker
    Получает ключ авторизации и задачу для парсинга после завершение возвращает результат генератору.
  • Parsed data publisher
    Получив результат от воркера, паблишит его всем сабскрайберам.
  • Alert system subscriber
    Получает данные и рассылает алерты, если нужно.
  • Upload system subscriber
    Получает данные и заливает их на сервер.
  • Data upload worker
    Енкодит, зипует и аплодит данные на сервер.
  • System monitor
    Собирает статистику системы в рейалтайме.


Архитектура получилась несложная, все компоненты были написаны отдельно от бизнес-логики, оформлены в пакет для композера и запаблишены на гитхаб:

https://github.com/limitium/zmq

Чтоб поковырять, нужно (на примере дебиан):

1. Установить ZeroMQ

   sudo apt-get update -qq
   sudo apt-get install -y libzmq3-dev

2. Установить байндинг php-zmq

   git clone https://github.com/mkoppanen/php-zmq.git
   sh -c "cd php-zmq && phpize && ./configure && make --silent && sudo make install"
   echo "extension=zmq.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`

3. Установить либу через composer

   composer require limitium/zmq


Дальше берем, например, psr-3 логгер и смотрим, как он работает:
Логгер
    $logger = new ZLogger('my_service_1', 'tcp://127.0.0.1:5555');
    $logger->info("core is stable");
    $logger->emergency("we're all going to die!");

Сборщик логов
   (new Concentrator('tcp://127.0.0.1:5555'))
        ->setReceiver(function ($logMsg) {
            $serviceName = $logMsg[0];
            $time = $logMsg[1];
            $logLevel = $logMsg[2];
            $logMsg = $logMsg[3];
        })
        ->listen();

Все просто, при этом логгер благодаря плюшкам ZeroMQ может работать как в рамках одного процесса, так и собирать информацию со 100500 серваков.

Пример генератора задач и воркера
Generator
    (new Ventilator('tcp://127.0.0.1:5555'))
        ->setGenerator(function () {
            sleep(1);
            return rand();
        })
        ->setResponder(function ($msg) {
            echo $msg;
        })
        ->listen();

Worker
    (new Worker('tcp://127.0.0.1:5555'))
        ->setExecutor(function ($msg) {
            return $msg + $msg;
        })
        ->work();


И под конец банальный pub/sub
Publisher
    $pub = new Publisher('tcp://127.0.0.1:5555');
    $pub->send('azaza');

Subscriber
    (new Subscriber('tcp://127.0.0.1:5555'))
        ->setListener(function ($msg){
            echo $msg;
        })
        ->listen();


Единственный минус ZeroMQ, который стоит отметить — чем больше интерпрзайности хочется от системы, тем больше придется писать кода. Но кого это волнует, когда запускается все в 2 строчки кода?
Tags:
Hubs:
+5
Comments 31
Comments Comments 31

Articles