Comments 10
Вышла хорошая лабораторная работа с неявной практичностью :)
Мне на php нужна была очередь, а подключать сторонние библиотеки не было желания. Требования к производительности позволяли использовать просто файлы для очереди с блокировкой на уровне файловой системы. В итоге сделал довольно простую и очевидную очередь на чанках. Добавление пакетов пишет в последний чанк, при его заполнении создает новый файл чанка. Считывание пакета считывает данные из чанка по указателю с его смещением. Как только все данные из чанка считаны, он удаляется, указатель переносится на следующий чанк. В итоге получилось элегантное решение с двумя точками доступа, одна это запись в конец списка, вторая считывания начиная с первого чанка. Добавление и получение из очереди блокируют очередь через flock($handle, LOCK_EX). Не тестировал, но уверен, что это решение более эффективно в плане производительности, чем использование Redis, RabbitMQ и им подобных (если требования позволяют)
Решение просто - тут спору нет.
Но работа на запись в фаил это 80 000 запросов в секунду (если процесс держит поток открытый и не делает fclose и fopen постоянно - то больше).
Минус этого подхода - эта очередь работает лишь на том сервере (железе) где у вас фаил. Redis и RabbitMQ полезные тем что они масштабируются (например есть приложение на одном сервере что пишет в очередь, а другое приложение в микро сервисной архитектуре его читает)
А как насчет задержки между игровым сервром и Redis/RabbitMQ? Она приемлема? В моем случае отказался от Redis именно из-за задержки.
Она примерно равна 0.02мс. времени на запись (в самом быстром случае) , но я не использую ее в игровом сервере. Redis используется в приложении авторизации по http на одной машине записывая временный ключ в кеш и websocket сервере когда человек устанавливает соединение читая кеш redis в асинхронном режиме что бы на это время не блокировать worker этого websocket сервера (их много , как с веб сервером). В игровом я использую очередь в оперативной памяти о которой писал в статье
Да вы правы, еще задержки будут при удалении считанного чанка. Чем больше размер удаляемого файла, тем больше задержка. На файловой системе ext4 и размере файла 200 гигабайт удаление могло занять секунд 10 и более. Но повторюсь, мои требования позволяли только локальный доступ к очереди и производительность мелких чанков устраивала.
для сравнения передача из потока (условно процесса) A в процесс B делается при скорости 1 600 000 пакетов в секунду и тут это важно тк нужно быстро освобождать процесс что бы он выполнял другую работу (тк пока он передает он ждет и не принимает новые соединения, не отправляет пакеты которые надо отправлять)
В предыдущей статье я упомянул что наш игровой сервер способен принимать множество запросов, но отдав результат на него позже (и в большинстве своем - всем игрокам).
На него - это на кого? Куда отдается результат?
На них* (описался). Тут речь про то, что в классическом http взаимодействии вы отправляете запрос и ждете ответа (например когда ждете загрузку страницы).
А с WebSocket у вас нет блокировки - вы отправляете пакет и возвращается управление (и у вас приходят пакеты , хотя ваш еще может и не быть обработан, но спустя какое то время и результат на ваш запрос придет и других игроков пакетом. Например когда много игроков отправили команды движения)
Создание сервера для онлайн ММО игр на PHP ч. 12 — Очереди и параллельное программирование на CPU