Важные аспекты разработки, о которых должен знать разработчик
1. Localzet Server не зависит от Apache или Nginx
Localzet Server сам по себе является контейнером, аналогичным Apache или Nginx, и может работать, если среда PHP нормально настроена.
2. Localzet Server запускается из терминала
Способ запуска аналогичен запуску Apache с помощью команды (в веб-пространстве его использовать нельзя). Экран запуска выглядит так:
3. Для длительных соединений следует использовать механизм "Cердцебиения"
Для длительных соединений обязательно использовать механизм "Cердцебиения". Это очень важно!!! При длительном отсутствии обмена данными соединение может быть прервано!
4. Протокол клиента и сервера должны соответствовать для взаимодействия
Это очень распространенная проблема среди разработчиков. Например, если клиент использует протокол WebSocket, то сервер должен также использовать протокол WebSocket (new Server('websocket://0.0.0.0...')
), чтобы соединение могло быть установлено и обмен данными был возможен.
Не пытайтесь обратиться к порту протокола WebSocket через строку адреса браузера или использовать протокол WebSocket для доступа к порту протокола голого TCP – протоколы должны соответствовать!
5. Не используйте операторы exit
, die
и sleep
Использование операторов exit
и die
в бизнес-логике приведет к закрытию всего процесса и отображению ошибки SERVER EXIT UNEXPECTED
.
Однако процесс будет немедленно перезапущен для продолжения обслуживания. Если нужно вернуть ответ, используйте оператор return
.
Оператор sleep
приостанавливает выполнение всего процесса, во время которого не выполняется никаких бизнес-операций, и работа фреймворка также останавливается,
что приводит к тому, что все запросы клиентов этого процесса остаются без обработки!
6. Не используйте функцию pcntl_fork
Функция pcntl_fork
используется для динамического создания новых процессов.
Если в бизнес-коде используется pcntl_fork
, это может привести к созданию родительского процесса,
который невозможно закрыть, что вызовет сбой бизнес-логики. Использование pcntl_fork
в бизнес-коде также повлияет на обработку событий,
связанных с подключениями, сообщениями, закрытием соединений, таймерами и приведет к непредсказуемым сбоям.
7. Не используйте бесконечные циклы в бизнес-коде
Не следует использовать бесконечные циклы в бизнес-коде, в противном случае процесс не сможет передать управление Localzet Server и он, как следствие, не сможет обрабатывать сообщения клиентов.
8. Перезапускайте код после его изменения
Localzet Server - это постоянный асинхронный фреймворк в памяти, поэтому для просмотра результатов изменений кода необходимо перезапустить его.
* Поддержка более высокой параллельности
Если количество одновременных подключений к бизнес-приложению превышает 1000, обязательно оптимизируйте ядро Linux и установите расширение event.
Особенности разработки на Localzet Server
1. Отличия от разработки на обычном PHP
Помимо того, что нельзя напрямую использовать переменные и функции, связанные с протоколом HTTP, разработка на Localzet Server не имеет существенных отличий от обычной разработки на PHP.
2. Различия в протоколах прикладного уровня
- В обычной разработке PHP обычно используется протокол прикладного уровня HTTP, где сервер веб-приложений уже выполняет разбор протокола.
- Localzet Server поддерживает различные протоколы, в настоящее время встроены HTTP, WebSocket и другие протоколы. Localzet Server рекомендует разработчикам использовать более простой пользовательский протокол обмена сообщениями.
Для разработки приложений, использующих протокол HTTP, см. раздел HTTP-сервер.
3. Различия в жизненном цикле запроса
- В PHP после завершения запроса к веб-приложению все переменные и ресурсы освобождаются.
- Приложения, разработанные на Localzet Server, остаются в памяти после первой загрузки и парсинга, что позволяет сохранить определение классов, глобальные объекты и статические члены класса для повторного использования.
4. Осторожно с повторным определением классов и констант
- Поскольку Localzet Server кеширует скомпилированные файлы PHP, необходимо избегать многократного использования
require
/include
для одного и того же определения классов или констант. Рекомендуется использоватьrequire_once
/include_once
для загрузки файлов.
5. Внимание к освобождению ресурсов в режиме единичного экземпляра
- Поскольку Localzet Server не освобождает глобальные объекты и статические члены класса после каждого запроса, в случае использования одиночного экземпляра, например, для базы данных, соединение с базой данных (включая сокетное соединение с базой данных) обычно сохраняется в статическом члене класса, что позволяет Localzet Server повторно использовать это сокетное соединение в течение жизненного цикла процесса. Следует учитывать, что если сервер базы данных обнаруживает неактивное соединение в течение определенного времени, он может закрыть сокетное соединение, что приведет к ошибке при повторном использовании этого экземпляра базы данных (например, подобной ошибке, как mysql gone away).
6. Кратковременное соединение
Кратковременное соединение означает установление соединения между обеими сторонами только в момент обмена данными, после передачи данных соединение закрывается. Например, HTTP-сервисы веб-сайтов обычно используют кратковременное соединение.
Разработка приложений с использованием кратковременного соединения можно найти в главе основного процесса разработки
7. Долгосрочное соединение
Долгосрочное соединение позволяет передавать несколько пакетов данных через одно соединение.
Примечание: приложения, использующие долгосрочное соединение, обязательно должны использовать сердцебиение, в противном случае соединение может быть разорвано межконечным маршрутизатором из-за неактивности в течение длительного времени.
Долгосрочное соединение широко используется в случае частой оперативности и точного взаимодействия. Каждое TCP-соединение требует выполнения трехэтапного рукопожатия, что занимает время. Если каждая операция начинается с установления соединения, то обработка замедлится. Поэтому при долгосрочном соединении после каждой операции соединение не закрывается, а следующий раз передается пакет данных напрямую, без установления TCP-соединения. Например, долгосрочное соединение используется для соединения с базой данных, и если использовать кратковременное соединение для частого общения, то возникнут ошибки в работе с сокетом, и инициирование сокета для каждой операции приведет к излишнему расходу ресурсов.
При разработке приложений с долгосрочным соединением см. процесс разработки шлюза/воркера
8. Различие между главным и дочерним процессами
Важно отметить, что код работает в главном процессе или в дочернем процессе. Обычно код, запускаемый до вызова Server::runAll();
, выполняется в главном процессе, а код, выполняемый в колбэках onXXX, относится к дочернему процессу. Следует учитывать, что код, написанный после вызова Server::runAll();
, никогда не будет выполнен.
Вот пример:
use localzet\Server;
use localzet\Server\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
// Код выполняется в главном процессе
$tcp_server = new Server("tcp://0.0.0.0:2347");
// Присваивание выполняется в главном процессе
$tcp_server->onMessage = function(TcpConnection $connection, $data)
{
// Этот код выполняется в дочернем процессе
$connection->send('hello ' . $data);
};
Server::runAll();
Примечание: не инициализируйте соединение с базой данных, memcache, redis и другие ресурсы в главном процессе, так как главный процесс может по умолчанию наследовать их у дочерних процессов (особенно при использовании единственных экземпляров). Это означает, что все процессы используют одно и то же соединение, и сервер возвращает данные через это соединение, которые могут быть прочитаны в нескольких процессах, что приводит к неправильным данным. Таким же образом, если хотя бы один процесс закрывает соединение (например, когда главный процесс завершается в режиме демона), все дочерние процессы будут закрыты и произойдут непредсказуемые ошибки, такие как mysql gone away. Рекомендуется инициализировать ресурсы соединения в обработчике onServerStart
.
9.Входной файл
Как и в приложениях PHP в среде nginx + PHP-FPM
, приложения в Localzet Server также требуют входного файла, имя которого не имеет определенных требований, и этот входной файл запускается в режиме PHP Cli.
Во входном файле содержится код, относящийся к созданию процесса прослушивания, например, следующий фрагмент кода, основанный на разработке с помощью Server:
test.php
<?php
use localzet\Server;
use localzet\Server\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
// Создание Server для прослушивания порта 2345 с использованием протокола HTTP
$http_server = new Server("http://0.0.0.0:2345");
// Запуск 4 процессов для предоставления услуг
$http_server->count = 4;
// Прием данных, отправленных браузером, и отправка браузеру сообщения "hello world"
$http_server->onMessage = function(TcpConnection $connection, $data)
{
$connection->send('hello world');
};
Server::runAll();