README.md

Пример 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)
Конвейеры
0 успешных
0 с ошибкой