Пример HTTP-сервера на PHP с использованием файберов
Сравнение HTTP-сервера приложений bin/server.php
, построенного на базе сокетов и файберов (расширение pcntl
нужно лишь для обработки сингала останова приложения SIGINT
или Ctrl+C
) и классической PHP-FPM реализации webroot/index.php
. Приложение конкурентно обрабатывает подключения, используя вызов socket_select()
и не так давно появившиеся в PHP файберы (класс Fiber
). Чтобы сделать такое приложение параллельным достаточно запустить несколько экземпляров (лучше по 1 инстансу на ядро процессора). Приложение в качестве хранилища использует Redis. Оно генерирует UUID
пользователя, сохраняет его и время регистрации в коллекцию Redis, затем генерирует JWT и возвращает его.
Инициализация и запуск
Для запуска потребуется docker-compose и утилита make, консольный текстовый редактор sed
, терминал Linux.
make create-env
docker-compose run php bash -c "cd app && composer install"
docker-compose up -d
#обращение к файберам
curl --request GET --url http://127.0.0.1:8085/
#обращение к PHP-FPM
curl --request GET --url http://127.0.0.1:8086/
Пример успешного ответа сервера:
{"jwt":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsInVzZXJfaWQiOiI3ZjBiN2IzZi1mY2MzLTRlNDItYWQxYS1hOTM1YzcxYzZiYTUiLCJjb3VudGVyIjoxMzU0ODl9.eyJpYXQiOjE3MzE2MDgwOTEuNjEzNjc0LCJleHAiOjE3MzE2MTE2OTEuNjEzNjc0fQ.Htlvwb1YRkLRZ3E6rFsnFb-p7rauccEw5eUwEjANiD0"}
Бенчмаркинг
Для лучшего, на мой взгляд, сравнения, контейнерам с приложениями выделено только по 1 ядру CPU с помощью опции cpu_count: 1
в файле docker-compose.yml
. Для бенчмаркинга была ипользована программа Apache Benchmark.
Установка Apache Benchmark
sudo apt-get install apache2-utils
Запуск бенчмарков
# файберы
ab -c 10 -n 1000 http://localhost:8085/
# FPM
ab -c 10 -n 1000 http://localhost:8086/
Результаты выполнения бенчмарков на моём компьютере (Windows 11, WSL2 Debian)
Файберы
Failed Requests (Length)
это число запросов, которые отличаются от первого ответа по размеру ответа. Т.к. приложение генерирует JWT и возвращает его в ответ, а JWT может иметь разную длину, ab
помечает это как ошибку длины ответа. Если просмотреть весь вывод ab
с помощью опции -v 2
, то там не будет ошибок, т.е. на эту цифру можно не обращать особого внимания.
$ ab -c 1000 -n 10000 http://localhost:8085/
This is ApacheBench, Version 2.3 <$Revision: 1913912 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.1.130 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests
Server Software:
Server Hostname: localhost
Server Port: 8085
Document Path: /
Document Length: 244 bytes
Concurrency Level: 1000
Time taken for tests: 54.569 seconds
Complete requests: 10000
Failed requests: 1020
(Connect: 0, Receive: 0, Length: 1020, Exceptions: 0)
Total transferred: 2946584 bytes
HTML transferred: 2436584 bytes
Requests per second: 183.25 [#/sec] (mean)
Time per request: 5456.885 [ms] (mean)
Time per request: 5.457 [ms] (mean, across all concurrent requests)
Transfer rate: 52.73 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 19 99.4 1 3157
Processing: 80 5183 926.8 5324 6389
Waiting: 4 5182 926.9 5323 6389
Total: 184 5202 908.1 5327 9381
Percentage of the requests served within a certain time (ms)
50% 5327
66% 5405
75% 5486
80% 5584
90% 5843
95% 6171
98% 6297
99% 6355
100% 9381 (longest request)
FPM
$ ab -c 1000 -n 10000 http://localhost:8086/
This is ApacheBench, Version 2.3 <$Revision: 1913912 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.1.130 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests
Server Software: nginx/1.27.2
Server Hostname: localhost
Server Port: 8086
Document Path: /
Document Length: 244 bytes
Concurrency Level: 1000
Time taken for tests: 94.832 seconds
Complete requests: 10000
Failed requests: 1011
(Connect: 0, Receive: 0, Length: 1011, Exceptions: 0)
Total transferred: 3666659 bytes
HTML transferred: 2436659 bytes
Requests per second: 105.45 [#/sec] (mean)
Time per request: 9483.242 [ms] (mean)
Time per request: 9.483 [ms] (mean, across all concurrent requests)
Transfer rate: 37.76 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 12 46.0 2 1078
Processing: 95 9037 1563.0 9462 10176
Waiting: 49 9036 1563.1 9462 10175
Total: 97 9049 1546.9 9465 10716
Percentage of the requests served within a certain time (ms)
50% 9465
66% 9566
75% 9634
80% 9660
90% 9724
95% 9754
98% 9782
99% 9806
100% 10716 (longest request)