Этот вопрос связан с теорией, как и с программированием в реальной жизни. Я впервые задал этот вопрос на (cs.stackexchange.com), потому что это теория, и у меня была инструкция спросить здесь (https://cs.stackexchange.com/questions/81472/question-about-implementing-websockets-theory-and-the-reality-in-php)
Я экспериментирую с веб-сокетами и PHP уже много лет (часть этого кода уже работает), сначала я создал сервер WebSocket (WS) с нуля с неблокирующим вводом-выводом, и все работало нормально, за исключением реальных методов, необходимых для приложение не может быть неблокирующим (например, подключение к БД и запрос). Затем я ввел асинхронное программирование, то есть WS-сервер инициировал различные PHP-запросы к серверу и проверял в каждом цикле, закончили ли эти запросы результаты, чтобы отправить их клиенту. Это работало хорошо для немногих пользователей на стороне клиента, подключенных к этому WS-серверу, число было связано с тем, какова была операция, но не было бы больше 30 или 50. Это было потому, что если вы используете только один поток и у вас есть много одновременных запросы вы должны проверить каждый из них последовательно, если есть готовый результат.
Следующим шагом было проанализировать код популярных подходов, утверждающих, что он может одновременно хранить и обрабатывать множество (некоторые говорят, 10000) клиентов. Возможно, они знали что-то, чего я не знал (моя проблема не в том, лгут ли они, проблема в том, есть ли здесь что-то, чего я упускаю (или, может, я ошибаюсь)). Результаты были разочаровывающими. Большинство из них не используют асинхронность по умолчанию, советуя вам не использовать методы блокировки (что на самом деле невозможно в программировании в реальной жизни), но даже если вы добавите к ним модули, чтобы сделать их асинхронными, та же проблема, что у меня возникла.
Вопрос не в том, что является решением, потому что я реализовал PHP pthreads и смог заставить его работать, но без реальной выгоды (например, при совместном использовании объектов он должен был сериализовать и не сериализовать все), я пишу расширения C ++ PHP уже несколько лет, поэтому Я работаю в расширении PHP, которое будет делать это эффективно.
Вопрос здесь в том, что я что-то упустил? Как они могут утверждать, что могут обрабатывать большое количество запросов одновременно, в то время как даже при асинхронном программировании они должны проверять каждый запрос в завершенном цикле?
Заранее благодарим вас за любые новые знания или указания для поиска, что ваш ответ может привести меня.
Да, есть проекты, которые делают это возможным с помощью PHP. Одним из таких проектов является ампер с этими Aerys HTTP и WebSocket сервер. Да, вы не можете просто вызывать блокирующие функции в одном потоке. Да, pthreads не поможет, это, в основном, просто запуск другого процесса PHP, потому что все в PHP ничего не передается. Но как это работает тогда?
Используйте неблокирующие реализации, где это возможно. Существуют библиотеки, которые работают с неблокирующим вводом / выводом для доступа к базе данных, такие как amphp/mysql
.
Если такой библиотеки нет, спросите, можно ли реализовать что-то подобное, если вы не хотите / не можете реализовать это самостоятельно.
Другая возможность заключается в использовании библиотек, таких как amphp/parallel
которые используют постоянных работников для блокировки задач. Порождение другого работника для каждой задачи блокировки будет ужасно неэффективным, так что библиотека позволяет легко использовать рабочие пулы и поддерживать этих рабочих для выполнения нескольких задач каждая.
Одна такая библиотека, которая использует amphp/parallel
является amphp/file
, который использует эти рабочие для неблокирующего доступа к файловой системе, когда нет таких расширений, как uv
или же eio
доступны, может быть, вы хотите, чтобы посмотреть на его ParallelDriver
.
Сколько соединений вы сможете обрабатывать одновременно, во многом зависит от вашего оборудования и от того, что вы делаете с этими соединениями. Если вы будете постоянно передавать данные каждому клиенту, вы сможете держать гораздо меньше открытых соединений, чем в ситуации, когда большинство соединений простаивают и отправляют / получают что-то только в небольшой части подключенного времени.
Если вы хотите обрабатывать более 1000 клиентов, вам, вероятно, понадобится расширение или перекомпиляция PHP из-за FD_MAXSIZE
за stream_select
, который компилируется и ограничивает stream_select
для файловых дескрипторов ниже 1024.
Других решений пока нет …