As part of this lecture, I will be able to share the experience of writing production code for an enterprise application in PHP that works under the WAMP protocol. I'll tell you about the real experience of using such technologies as WAMP, Crossbar, Thruway, spawning of child processes, communication between the child and the host process. I'll tell you about the questions and difficulties that we faced, and, of course, about how we solved them. I can also add that we used this approach to the development of the application, launching sales for Eurovision 2017. The approach was tested in the most combat conditions.
2. Написание multi-process runtime
приложений на PHP
• WAMP – The Web Application Messaging Protocol
• Crossbar.io – open source WAMP router
• voryx/Thruway – WAMP client implementation (PHP)
• WyriHaximus/reactphp-child-process-pool
3. WAMP - Web Application Messaging Protocol
WAMP – протокол прикладного уровня, реализует 2 паттерна:
RPC – Remote Procedure Call
PubSub – Publish/Subscribe
Работает поверх протокола TCP/IP, по умолчанию в качестве транспорта использует
Websockets.
4. WAMP - Web Application Messaging Protocol
Имеет структуру взаимодействия «клиент-клиент» + маршрутизатор (роутер).
Клиенты подключаются к маршрутизатору
Маршрутизатор выдает клиентам права на текущий сеанс
Клиенты отправляют сообщение маршрутизатору, он перенаправляет их получателям
5. WAMP - Web Application Messaging Protocol
RPC & Pub/Sub из коробки
Открытый стандарт
Web Native
Cross language
6. WAMP - Web Application Messaging Protocol
Предоставляет открытый стандарт обмена сообщениями между отдельными компонентами
приложения в реальном времени.
7. WAMP - Web Application Messaging Protocol
Routing of both: events and rpc calls in one protocol
8. Вызов RPC – Старый добрый подход
Чтобы Caller мог вызвать Callee:
9. Вызов RPC – Старый добрый подход
Чтобы Caller мог вызвать Callee:
Caller должен знать, где находится Callee
10. Вызов RPC – Старый добрый подход
Чтобы Caller мог вызвать Callee:
Caller должен знать, где находится Callee
Должен знать, как обратиться к Callee
11. Вызов RPC – Старый добрый подход
Чтобы Caller мог вызвать Callee:
Caller должен знать, где находится Callee
Должен знать, как обратиться к Callee
Тесная связь между Callee и Caller ведет к усложнению приложения.
13. Вызов RPC – WAMP
Caller и Callee – общаются через
посредника, которым выступает Dealer.
14. Вызов RPC – WAMP
Когда Caller хочет вызвать Callee, он обращается к Dealer, предоставляя
ему URI вызываемой процедуры и аргументы вызова.
15. PubSub – WAMP
Когда Caller хочет вызвать Callee, он обращается к Dealer, предоставляя
ему URI вызываемой процедуры и аргументы вызова.
16. PubSub – WAMP
Publisher отправляет информацию в абстрактный “topic”.
Subscriber подписывается на определенные “topic”.
Broker знает, кто на что подписан.
17. PubSub – WAMP
Publisher отправляет информацию в абстрактный “topic”.
Subscriber подписывается на определенные “topic”.
Broker знает, кто на что подписан.
В модели Pub/Sub определение подписчиков и направление
информации подписчикам – называется routing.
20. Crossbar.IO - An advanced, open-source
WAMP router
Принимает соединения от WAMP клиентов и занимается маршрутизацией вызовов и событий
между ними.
21. Crossbar.IO - An advanced, open-source
WAMP router
Принимает соединения от WAMP клиентов и занимается маршрутизацией вызовов и событий
между ними.
RPC & Pub/Sub Routing
Realms (domains)
Multi-transport (WebSockets, Raw sockets, HTTP Long Poll)
22. Thruway - Open source client and router
implementation of WAMP, for PHP
Использует ReactPHP.
Отлично подходит для реализации real-time приложения на PHP.
23. Thruway - Open source client and router
implementation of WAMP, for PHP
• URI: com.vticket.shoppingcart.create
• [{“eventId”: 2008, “userId”: 280}]
• public function __invoke(RequestInterface $requestMessage)
{
$eventId = $requestMessage->getAttribute('eventId');
$sellerId = $requestMessage->getAttribute('userId');
$order = $this->orderFactory->makeOrder($eventId, $sellerId);
$this->orderRepository->save($order);
return $this->response->response($order);
}
26. WyriHaximus/reactphp-child-process-pool
Компонент для ReactPHP, который позволяет реализовать child process pooling и организовать
обмен сообщениями между родительским host-процессом и его дочерними процессами.
Автор разработал multi-process messenger, который позволяет реализовать RPC-like
коммуникацию между родительским и дочерними процессами.
27. WyriHaximus/reactphp-child-process-pool
”react/child-process is very flexible and can work a lot of ways but sometimes you don't want to be
bothered with the details of how it works and just want a simpler API to do that.”
Проект вырос из обертки над react/child-process, которая брала на себе всю работу по
коммуникации между процессами, в отдельный компонент для ReactPHP.
30. WyriHaximus/reactphp-child-process-pool
Fixed – пулл с фиксированным количеством дочерних процессов
$loop = EventLoopFactory::create();
$options = [ Options::SIZE => 5, ];
Fixed::createFromClass(ReturnChild::class, $loop, $options)->then(function (PoolInterface $pool) {
// You now have a pull with 5 always running child processes
});
31. WyriHaximus/reactphp-child-process-pool
Flexible – пулл с плавающим количеством дочерних процессов
$loop = EventLoopFactory::create();
$options = [ Options::MIN_SIZE => 0, Options::MAX_SIZE => 5, Options::TTL => 0, ];
Flexible::createFromClass(ReturnChild::class, $loop, $options)->then(function (PoolInterface $pool) {
// You now have a pool that spawns no child processes on start.
// But when you call rpc a new child process will be started for
// as long as the pool has work in the queue. With a maximum of five.
});
32. Multi-process WAMP application
ApplicationHostProccess.php
public function run($action, ServerRequestInterface $request) : PromiseInterface
{
$msgFactory = $this->msgFactory;
return $this->pool->rpc(Factory::rpc(
ApplicationProcess::RPC_RUN,
[
ChildProcessApp::PAYLOAD_ACTION => $action,
ChildProcessApp::PAYLOAD_REQUEST => $request->getAttributes()
]
))->then(
function (Payload $payload = null) use ($msgFactory) {
$result = $payload ? $payload->getPayload() : [];
return $msgFactory->makeResponseMessage($result);
},
function (Exception $exception) use ($msgFactory) {
return $msgFactory->makeResponseMessageByThrowable($exception);
}
);
}
33. Multi-process WAMP application
ApplicationProccess.php
public function __construct(Messenger $messenger, LoopInterface $loop)
{
$messenger->registerRpc(static::RPC_BUILD, function (Payload $payload) {
$build = $payload[static::PARAM_BUILD];
$config = $payload[static::PARAM_CONFIG];
$this->app = $this->build($build, $config);
});
$messenger->registerRpc(static::RPC_RUN, function (Payload $payload) {
return resolve($this->app->run($payload));
});
}