Jak poprawić wydajność aplikacji pisanych z Laravel za pomocą Swoole używając Dockera?
Czy wiesz, że skrypty PHP mogą działać asynchronicznie? Wiele firm wybiera języki, takie jak Java, .Net lub NodeJS, aby tworzyć wysokowydajne aplikacje lub usługi oparte na WebSocket, ale istnieje również możliwość zrobienia tego w języku PHP.
Sposobem na to jest...Swoole.
Dzięki Swoole programiści PHP mają możliwość pisać aplikacje, które działają tak samo szybko jak te odpalane z Node.js. W moim wpisie postaram się przedstawić bliżej to narzędzie, które może radykalnie zwiększyć wydajność aplikacji pisanych w oparciu o Laravel. Pokaże też Ci krok po kroku, jak postawić środowisko i odpalić projekt ze Swoole + Docker.
Czym jest Swoole?
Jak napisałem powyżej, Swoole jest frameworkiem, ponadto warto wiedzieć, że został napisany w C. Chyba teraz wiadomo już skąd ta wydajność. Framework ten pozwala programistom PHP tak jak i programistom Java, Go, Node.js pisać aplikacje o wysokiej wydajności, skalowalne, współbieżne TCP, UDP, Unix socketowe, HTTP oraz serwisy oparte o websockety. Ponadto, warto zauważyć, że Swoole umożliwia pisanie współprogramów (en. Coroutine) (z tego samego rozwiązania korzystają i się tym szczycą programiści Kotlin czy też Pythona). Najprościej pisząc, oznacza to, że programista może pisać asynchroniczne aplikacje w sposób sekwencyjny (bez callbacków). Aczkolwiek jest to tak złożone zagadnienie, że nie będę tego poruszał w tym artykule, zwłaszcza, że według mnie jest to mało (a szkoda) używane obecnie podejście w technologii PHP.
Dane wzięte z TechEmpower.
Jak zainstalować Swoole w środowisku Docker?
W moim przykładzie będę pracował z Dockerem. A zatem jeśli jeszcze nie używałeś go, to warto zajrzeć do mojego artykułu na ten temat (sam używam Laradock).
Zakładam, że masz już wiedzę, na temat pracy z Dockerem, więc przejdźmy dalej. Najpierw otwórzmy plik .evn i włączmy Swoole zarówno w kontenerze workspace jak i w php-fpm.
cd laradock
vim .env
WORKSPACE_INSTALL_SWOOLE=true
PHP_FPM_INSTALL_SWOOLE=true
Swoole pracuje domyślnie na porcie 1251, dlatego też musimy w workspace wystawić ten port na zewnątrz.
cd laradock
vim workspace/Dockerfile
Dodajmy komendę EXPOSE na końcu pliku konfiguracyjnego kontenera.
EXPOSE 1251
Skonfigurujmy nginxa pod nasz alias aplikacji.
cd laradock
vim nginx/sites/api-swoole.conf
upstream swoole-http {
server workspace:1215;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
# listen [::]:80;
root /var/www/api-swoole/public;
index index.php index.html;
server_name api-swoole.test;
location = /index.php {
# Ensure that there is no such file named "not_exists"
# in your "public" directory.
try_files /not_exists @swoole;
}
location / {
try_files $uri $uri/ @swoole;
}
location @swoole {
set $suffix "";
if ($uri = /index.php) {
set $suffix ?$query_string;
}
proxy_set_header Host $http_host;
proxy_set_header Scheme $scheme;
proxy_set_header SERVER_PORT $server_port;
proxy_set_header REMOTE_ADDR $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# IF https
# proxy_set_header HTTPS "on";
charset utf-8;
proxy_pass http://swoole-http$suffix;
}
error_log /var/log/nginx/laravel_error.log;
access_log /var/log/nginx/laravel_access.log;
}
Czas na przebudowanie i zrestartowanie kontenerów.
cd laradock
docker-compose build workspace nginx php-fpm
#if containers are running
docker-compose restart workspace nginx php-fom
#if containers are not running
docker-compose up -d workspace nginx php-fpm
Nasz Docker jest juz odpalony z naszymi kontenerami i mamy zainstalowane Swoole :) Przejdżmy do powłoki kontenera workspace, wykonując poniższą komendę w katalogu głównym Laradocka.
docker-compose exec --user=laradock workspace bash
Teraz możemy zainstalować paczkę laravel -swoole, która ułatwi nam współpracę Laravel ze Swoole.
cd api-swoole
composer require swooletw/laravel-swoole
Dodajmy do naszego .evn dwie zmienne. Więcej informacji o możliwych konfiguracjach znajdziesz tutaj.
vim .env
SWOOLE_HTTP_HOST=workspace
SWOOLE_HTTP_DAEMONIZE=true
Po zapisaniu zmian, uruchomiamy serwer HTTP ze Swoole jako daemon.
php artisan swoole:http start
Jeśli wszystko pójdzie dobrze to dostaniemy na wyjściu taki komunikat:
Starting swoole http server...
Swoole http server started
Teraz już aplikacja jest uruchomiona na Swoole!
Pamiętaj, że zawsze po zmianie w kodzie należy zrestartować serwer HTTP używając poniższej komendy:
php artisan swoole:http restart
Podsumowanie
Dzięki Swoole możemy tworzyć aplikację o bardzo dużej wydajności i niezawodności. Aplikacja jest w stanie obsłużyć znacznie więcej żądań niż jest to możliwe w standardowej konfiguracji (nginx+php-fpm). Z ciekawości pozwoliłem sobie przeprowadzić własne benchmarki, które pokazują, że ze Swoole możemy obsłużyć 5-6 razy więcej requestów.
Poniżej zamieszczam kod benchmarka (na maszynie 16 GiB RAM, Intel® Core™ i7-8550U CPU @ 1.80GHz × 8, 250 GB SSD, Linux/Ubuntu 18.04).
Swoole daje Ci możliwość tworzenia niesamowicie wydajnych web API oraz serwisów opartych o websockety bez rezygnowania z dobrodziejstw, jakie daje nam Laravel. Narzędzie to daje programistom PHP możliwość pracy przy projektach złożonych i o wysokiej wydajności. Jeśli jednak zamierzasz stworzyć aplikację, która powinna obsłużyć bardzo dużą ilość requestów i poradzić sobie z dużymi obciążeniami, to lepiej nie używać wtedy żadnego frameworka i stworzyć natywną aplikację jedynie ze Swoole.