Важные аспекты разработки, о которых должен знать разработчик

1. Localzet Server не зависит от Apache или Nginx

Localzet Server сам по себе является контейнером, аналогичным Apache или Nginx, и может работать, если среда PHP нормально настроена.

2. Localzet Server запускается из терминала

Способ запуска аналогичен запуску Apache с помощью команды (в веб-пространстве его использовать нельзя). Экран запуска выглядит так: Запуск Localzet Server

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();