Speed up your web API with Laravel and Swoole using Docker

Did you know that PHP scripts can work asynchronously? Many companies choose languages like Java, .Net or NodeJS to create high-performance applications or WebSocket services but there exists a possibility also to do it with PHP language.
And I mean... Swoole.
It is an asynchronous programming framework for PHP, which makes PHP as fast as Node.js (or even faster). In my article, I'll explain to you how thanks to this framework, we can speed up our application developed with Laravel and how to do it.
What is Swoole?
As I've written before, Swoole is a framework, you should also know that it is written using C language. It allows PHP developers to write high-performance, scalable, concurrent TCP, UDP, Unix socket, HTTP, Websocket services in PHP. Moreover, Swoole is a coroutine framework (such as Kotlin Coroutine or Python Coroutine). It means that it allows you to write asynchronous code without using callbacks, i.e. sequentially. But this is a subject on the other article, especially that, I figure PHP developers have not used this solution too often yet.

Data were taken from TechEmpower.
How to install Swoole?
In my case, I'll use Docker as a work environment for my application. Before we start, you can check out my article about working with Docker (I use Laradock).
I assume that you've installed Laradock and we can go further. Firstly open your .env file and enable Swoole in your workspace and php-fpm containers.
cd laradock
vim .env
WORKSPACE_INSTALL_SWOOLE=true
PHP_FPM_INSTALL_SWOOLE=true
Swoole works on port 1251, so we must expose this port in our workspace.
cd laradock
vim workspace/Dockerfile
Add EXPOSE command to the end of your workspace' configuration file.
EXPOSE 1251
Now, we can configure nginx.
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;
}
It is an appropriate moment to rebuild and restart containers.
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
We have run Docker and installed Swoole. Move to your workspace container and run below command.
docker-compose exec --user=laradock workspace bash
Now, we can install a laravel-swoole package, which allows Laravel to cooperate with Swoole.
cd api-swoole
composer require swooletw/laravel-swoole
Add two variables to Laravel .env file. If you want to know more about configuration, you should follow this link.
vim .env
SWOOLE_HTTP_HOST=workspace
SWOOLE_HTTP_DAEMONIZE=true
Now, you can start Swoole HTTP server, which will work as a daemon.
php artisan swoole:http start
If everything has gone well, you should get this message.
Starting swoole http server...
Swoole http server started
At the moment your application works via Swoole HTTP server!
Remember that if you change anything in your code, you must reload server using a command bellow:
php artisan swoole:http restart
Summary
Swoole makes your application more efficient and stable. It allows handling much more requests than usually is possible using nginx+php-fpm. Below you can find my benchmark which proves that you can speed up your project event 5-6 times.
Below you can also find a code of my benchmark and results (16 GiB RAM, Intel® Core™ i7-8550U CPU @ 1.80GHz × 8, 250 GB SSD, Linux/Ubuntu 18.04).
Swoole gives you the possibility to create awesome web API or Websocket service without the resignation of Laravel abilities. It's a great tool which can help PHP developers write a complex and high-performance application, however, in my opinion, you should not use any framework with Swoole if you expect very heavy traffic and server load.