Upload
alexandre-kalendarev
View
99
Download
4
Embed Size (px)
Citation preview
Готовим кролика
10 рецептов
Календарев А.М.
Пару слов об pipeline архитектуреhttps://habrahabr.ru/company/oleg-bunin/blog/310418/
Pipe-line архитектура
Pipe-line архитектура
ApplicationApplication Application
Пример: аналог Yandex.market
Пример: аналог Yandex.market
ЗагрузкаYML
Сведениев pricelist
ПарсингYML
Загрузкаimg
Задачи за кадром
Пример: аналог Yandex.market
ЗагрузкаYML
Сведениев pricelist
ПарсингYML
Загрузкаimg
Задачи за кадром
Паттерны сообщений
Cообщения
● Позволяют асинхронно взаимодействоавть между элементами архитектуры
● Сохраняют слабую связанность между элементами архитектуры
● Позволяют взаимодействоавть с разными
частями, PHP – Phython – Java - Go ...
Паттерны сообщений
Pipeline & Filter
Не совсем pipeline
ЗагрузкаYML
ПарсингYML
Загрузкакартинок
Publish-Subscriber Channel
Routers
AdvancedMessageQueueProtocol
Exchange
● Принимает сообщения
● Имеет имя
● Имеет тип:- fanout- direct- topic - headers
AMQP : Exchange (обмен)
Exchange
AMQP : Exchange (обмен)● Принимает сообщения
● Имеет имя
● Имеет тип
Имеет свойства:- autodelete- transit- durable
Exchange
AMQP : Exchange (обмен)
$exchange = new AMQPExchange($channel);$exchange->setName('MyExchange';)$exchange->declare();
AMQP : Queue (очередь)
Queue
● Отдает сообщения адресату по принципу FIFO
● Имеет имя● Имеет свойства:
- autodelete- durable- exclusive
AMQP : Queue (очередь)
Queue
$queue = new AMQPQueue($channel);$queue->setName('MyQueue');$queue->declare();
AMQP : Bind (связь)
● Между Exchange и Queue определяем связь (или маршрут): Bind
● Имеет ключ RoutingKey, в соответствии с которым определяется маршрут сообщения
QueueExchangeBind
AMQP : Bind (связь)
QueueExchangeBind
$queue = new AMQPQueue($channel);$queue->setName('MyQueue');$queue->bind('MyExchange', $key);
AMQP : Bind (связь)
QueueExchangeBind
$exchange = new AMQPExchange($channel);$exchange->setName('MyExchange');$exchange->bind('MyQueue', $key);
AMQP : Bind (связь)
QueueExchangeBind
$exchange = new AMQPExchange($channel);$exchange->setName('MyExchange');$exchange->bind('MyQueue', $key);
Объявляется один раз
AMQP : Internals
AMQP : Message
Exchange
Состоит:
● тела
● routing key
● заголовков
● имеет аттрибуты
AMQP : Message
● Expiration period
● Message publishing timeshamp
Exchange
Аттрибуты:
● Content-type
● Content-encoding
● Delivery-mode
● Message priority
● Application id
AMQP : Message
Exchange
AMQP : Message
В зависимости от типа Exchange и routingKey сообщения определяется маршрут сообщения
Queue 1
Queue 2
Exchange
AMQP : Message
Fanout – ключ не учитываем
Direct – полное совпадение
Topic – совпадение по маске
Queue 1
Queue 2
Exchange
AMQP : Message
Fanout – самый быстрый
Direct – середина на половине
Topic – сомый медленный
Queue 1
Queue 2
Exchange
Отправить сообщение
$exchange = new AMQPExchange($channel);$exchange->setName('MyExchange';)$exchange->publish($message, $key);
AMQP : ACK
QueueExchangeBind
На каждое принятое сообщение должна быть отослана “квитанция” ACK (Acknowledgements).
AMQP : ACK
QueueExchangeBind
На каждое принятое сообщение должна быть отослана “квитанция” ACK (Acknowledgements).
Если Очередь имеет св-во AUTOACK то подтверждение специально отправлять не нужно
ACK
Guaranteed Delivery
AMQP : ACK
workerWEB
Заказ
AMQP : ACK
workerWEB
Заказ
ACK
Удачное соединение
AMQP : ACK
workerWEB
Заказ
Удачное соединениеНе удачнонесоединение
Делаем повторный запрос
Объявление очереди и обмена
// создание очереди, обмена и их привязки друг к другу. $rabbit = new AMQPConnection();$res = $rabbit->connect();
$channel = new AMQPChannel($rabbit);$exchange = new AMQPExchange($channel);$exchange->setFlags(AMQP_DURABLE);$exchange->setName('to_worker');$exchange->setType('direct');$exchange->declare();
$queue = new AMQPQueue($channel);$queue->setFlags(AMQP_DURABLE);$queue->setName('worker');
Объявление очереди и обмена
// создание очереди, обмена и их привязки друг к другу. $rabbit = new AMQPConnection();$res = $rabbit->connect();
$channel = new AMQPChannel($rabbit);$exchange = new AMQPExchange($channel);$exchange->setFlags(AMQP_DURABLE);$exchange->setName('to_worker');$exchange->setType('direct');$exchange->declare();
$queue = new AMQPQueue($channel);$queue->setFlags(AMQP_DURABLE);$queue->setName('worker');
AMQP_DURABLEAMQP_AUTODELETEAMQP_EXCLUSIVEAMQP_INTERNALAMQP_IMMEDIATEAMQP_AUTOACK
Объявление очереди и обмена
// создание очереди, обмена и их привязки друг к другу. $rabbit = new AMQPConnection();$res = $rabbit->connect();
$channel = new AMQPChannel($rabbit);$exchange = new AMQPExchange($channel);$exchange->setFlags(AMQP_DURABLE);$exchange->setName('to_worker');$exchange->setType('direct');$exchange->declare();
$queue = new AMQPQueue($channel);$queue->setFlags(AMQP_DURABLE);$queue->setName('worker');
AMQP_DURABLEAMQP_AUTODELETEAMQP_EXCLUSIVEAMQP_INTERNALAMQP_IMMEDIATEAMQP_AUTOACK
Это можно сделатьодин раз
Привзка очереди к обмену
$rabbit = new AMQPConnection();$res = $rabbit->connect();$channel = new AMQPChannel($rabbit);$queue = new AMQPQueue($channel);$queue->setName('worker');// $queue->declare();
$queue->bind('to_worker', 'logs');$rabbit->disconnect();
Привзка очереди к обмену
$rabbit = new AMQPConnection();$res = $rabbit->connect();$channel = new AMQPChannel($rabbit);$queue = new AMQPQueue($channel);$queue->setName('worker');// $queue->declare();
$queue->bind('to_worker', 'logs');$rabbit->disconnect();
Routing key
Привзка очереди к обмену
Это можно сделатьодин раз
Привзка очереди к обмену
$rabbit = new AMQPConnection();$res = $rabbit->connect();$channel = new AMQPChannel($rabbit);$queue = new AMQPQueue($channel);$queue->setName('worker');// $queue->declare();
$queue->bind('to_worker', 'logs');$rabbit->disconnect();
Это можно вообще не делать
а использоватьHTTP интерфейс
Публикация сообщения
$rabbit = new AMQPConnection();$res = $rabbit->connect();
$channel = new AMQPChannel($rabbit);$exchange = new AMQPExchange($channel);$exchange->setName('to_worker');$i=0;
while ($i < 20) { $i++; $data = json_encode([1,2,3, rand(0, 1000)]); $exchange->publish($data, 'logs', 0, ['delivery_mode'=>2, 'content_type'=> 'text/json'] );}
Публикация сообщения
$rabbit = new AMQPConnection();$res = $rabbit->connect();
$channel = new AMQPChannel($rabbit);$exchange = new AMQPExchange($channel);$exchange->setName('to_worker');$i=0;
while ($i < 20) { $i++; $data = json_encode([1,2,3, rand(0, 1000)]); $exchange->publish($data, 'logs', 0, ['delivery_mode'=>2, 'content_type'=> 'text/json'] );}
Routing key Persisten
Синхронное / Асинхронное
Асинхронное GET
$rabbit = new AMQPConnection(); $rabbit->connect();
$channel = new AMQPChannel($rabbit$queue = new AMQPQueue($channel); $queue->setName('worker'); $msg = $queue->get();
Асинхронное GET
Синхронное CONSUMEfunction processMessage($envelope, $queue) { echo 'Message: [', $envelope->getDeliveryTag(), ']', $envelope->getBody(),PHP_EOL; $queue->ack( $envelope->getDeliveryTag() );}
$rabbit = new AMQPConnection();$res = $rabbit->connect(); $channel = new AMQPChannel($rabbit);
$queue = new AMQPQueue($channel); $queue->setName('worker');$queue->setFlags(AMQP_EXCLUSIVE);$queue->consume("processMessage");
Синхронное CONSUMEfunction processMessage($envelope, $queue) { echo 'Message: [', $envelope->getDeliveryTag(), ']', $envelope->getBody(),PHP_EOL; $queue->ack( $envelope->getDeliveryTag() );}
$rabbit = new AMQPConnection();$res = $rabbit->connect(); $channel = new AMQPChannel($rabbit);
$queue = new AMQPQueue($channel); $queue->setName('worker');$queue->setFlags(AMQP_EXCLUSIVE);$queue->consume("processMessage");
function processMessage($envelope, $queue) { echo 'Message: [', $envelope->getDeliveryTag(), ']', $envelope->getBody(),PHP_EOL; $queue->ack( $envelope->getDeliveryTag() );}
$rabbit = new AMQPConnection();$res = $rabbit->connect(); $channel = new AMQPChannel($rabbit);
$queue = new AMQPQueue($channel); $queue->setName('worker');$queue->setFlags(AMQP_EXCLUSIVE);$queue->consume("processMessage");
Синхронное CONSUME
Асинхронное GET
Publish/Consume
Publish/Consume
В RannitMQработает не так как ожидается
Publish/Consume
ЗагрузкаYML
ПарсингYML
Загрузкакартинок
Publish/Consume
ЗагрузкаYML
ПарсингYML
Загрузкакартинок
50%
50%
Publish/Consume
ЗагрузкаYML
ПарсингYML
Загрузкакартинок
50%
50%
Потеря 50% контента
Publish/Consume
ЗагрузкаYML
Загрузкакартинок
Загрузкакартинок
50%
50%
Publish/Consume
ЗагрузкаYML
Загрузкакартинок
Загрузкакартинок
33.3%
33.3%
33.3%Загрузкакартинок
Publish/Consume
ЗагрузкаYML
ПарсингYML
Загрузкакартинок
Channel -1
Channel -2
Несколько каналов
ПарсингYML
Загрузкакартинок
Channel -1
Channel -2
ЗагрузкаYML content
parsing
uploadingExchange: Content, funout, Bind: parsing durable Bind: uploading
Queue 1: parsing, durable
Queue 2: uploading, durable
Несколько каналов(вар 2)
ПарсингYML
Загрузкакартинок
Channel -1
Channel -2
ЗагрузкаYML content
parsing
uploadingExchange: Content, header, durable
Queue 1: parsing, durable
Queue 2: uploading, durable
Bind: operation:x-parsing Bind: operation:x-uploading
Несколько каналов(вар 2)
ПарсингYML
Загрузкакартинок
Channel -1
Channel -2
ЗагрузкаYML content
parsing
uploadingExchange: Content, header, durable
Queue 1: parsing, durable
Queue 2: uploading, durable
Bind: operation:x-parsing Bind: operation:x-uploading
Несколько каналов(вар 2)
ПарсингYML
Загрузкакартинок
Channel -1
Channel -2
ЗагрузкаYML content
parsing
uploadingExchange: Content, header, durable
Queue 1: parsing, durable
Queue 2: uploading, durable
Bind: operation:x-parsing Bind: operation:x-uploading
Несколько каналовimport pikaconnection = pika.BlockingConnection()ch = connection.channel()ch.queue_bind( exchange='content', queue='parser', arguments={'operation': 'parsing', 'x-match':'any'})
Несколько каналовimport pikaconnection = pika.BlockingConnection()ch = connection.channel()ch.queue_bind( exchange='content', queue='parser', arguments={'operation': 'parser', 'x-match':'any'})
в PHPНельзя задать
аргументы для Bind
Несколько каналов
$exchange = new AMQPExchange($channel);$exchange->setName('to_worker');$ex->setType(AMQP_EX_TYPE_HEADERS);
$data = json_encode([1,2,3]);$headers = ['operation' => 'parsing'];$args = [ 'content_type'=> 'text/json', 'headers' => $headers ];$exchange->publish($data,'work',0,$args);
Несколько каналов
$exchange = new AMQPExchange($channel);$exchange->setName('to_worker');$ex->setType(AMQP_EX_TYPE_HEADERS);
$data = json_encode([1,2,3]);$headers = ['operation' => 'parsing'];$args = [ 'content_type'=> 'text/json', 'headers' => $headers ];$exchange->publish($data,'work',0,$args);
Несколько каналов(вар 2)
Синхронное / Асинхронноеwhat is the question ?
WEB AJAX лучше асинхронное
WebSocket Синхронное
Синхронное / Асинхронное
WEB AJAX лучше асинхронное
AMQP REST https://github.com/akalend/amqp-rest
Синхронное / Асинхронное
WEB AJAX лучше асинхронное
AMQP REST https://github.com/akalend/amqp-rest
NGX-AMQP https://github.com/WPMedia/nginx-amqp
Синхронное / Асинхронное
WEB AJAX лучше асинхронное
AMQP REST https://github.com/akalend/amqp-rest
NGX-AMQP https://github.com/WPMedia/nginx-amqpНадо делать через Upstreem & subquery
Синхронное / Асинхронное
WEB AJAX лучше асинхронное
AMQP REST https://github.com/akalend/amqp-rest
NGX-AMQP https://github.com/WPMedia/nginx-amqp
NGX-RABBIT https://github.com/wingify/lua-resty-rabbitmqstomp
Синхронное / Асинхронное
WebSocket Синхронное
NGX-RABBIT https://github.com/wingify/lua-resty-rabbitmqstomp
Node.js
Routers
Exchange
Route Message
Direct – совпадение по ключу
● Bind Queue_1 logs
● Bind Queue_2 worker
Queue 1
Queue 2
Exchange
Route Message
Headers – совпадение по заголовку
● Bind Queue_1 {'operation' : 'logs', 'x-match':'any'}
● Bind Queue_2 {'operation' : 'worker' , 'x-match':'any'}
Queue 1
Queue 2
Messages
Варианты использования сообщений
Варианты использования сообщений
Паттерн: данные
workerWEB
Заказ
ПередачаЗаказа
Варианты использования сообщений
Загрузка видео с видео хостинга
LoadConvertWEB
Клиентскийскрипт
Получаем статусВыполнено
Curl
Channels
Poin-to-Point Channel
Poin-to-Point Channel
Exchange : durableQueue : durable, exclusive
Guaranteed Delivery
Guaranteed Delivery
Exchange : durable= 1Message : delivery-type = 2Queue : durable= 1, autodelete = 0, autoack = 1
Guaranteed Delivery
$delivery-tag = $message->delivery-tag;$queue->ack($delivery-tag);
Dead letter channel
Запасной канал
$exchange = new AMQPExchange($channel);$exchange->setFlags(AMQP_DURABLE);$exchange->setName('to_worker');$exchange->setType(AMQP_EX_TYPE_DIRECT);$exchange->declare();
$queue = new AMQPQueue($channel);$queue->setFlags(AMQP_AUTODELETE);$queue->setName('worker');$queue->declare();
$queue->bind('to_worker', 'work');$queue->setFlags(AMQP_DURABLE);$queue->setName('garbage');$queue->declare();$queue->bind('to_worker', 'work');
Запасной канал
Запасной канал
$queue->setName('worker');$queue->delete();$queue->setArgument('x-dead-letter-exchange','garbage');$queue->declare();$queue->bind('to_worker', 'work');
Request Reply
Correlation Identifier
Correlation Identifier
$cr_id = $message->getArgument('correlation_id');
$exchange->publish( $message, '', ['correlation_id=>$cr_id]);
Datatype channel
debugging
Debugging
Java -cp rabbitmq-client.jar:commons-io-1.2.jar:commons-cli-1.1.jar com.rabbitmq.tools.Tracer677
Rabbit MQ
2015 № 11
Кролик в песочнице
Rabbit MQ
2015 № 12
RabbitMQ. Вырастаем из штанишек.
книги
книги
книги
книги
Cпасибо за внимание