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 с ошибкой