基于 Swoole 构建高性能 Laravel 应用系列 —— 基于 Swoole 实现高性能 HTTP 服务器

上篇教程中,学院君给大家介绍了 Swoole 的基本概念和安装配置,从这篇教程开始,学院君将结合 Laravel 框架在应用中通过 Swoole 实现高性能 HTTP 服务器、WebSocket 服务器、协程、异步事件监听、异步任务队列、毫秒级任务调度、MySQL 线程池等高级特性,从而提高 Laravel 应用整体性能。

当然,这些特性都是 Swoole 底层所支持的,并且已经有第三方扩展包 LaravelS 将其整合到 Laravel 框架,我们可以通过这个扩展包轻松在 Laravel 应用中实现上述特性。接下来,我们就来演示如何通过这个扩展包在 Laravel 框架中基于 Swoole 的这些特性来实现高性能 Laravel 应用。

需要声明的是,基于 Swoole 特性提升应用性能只是提高应用整体性能的一种方式,不是唯一方式。LaravelS 也不是在 Laravel 框架中使用 Swoole 的唯一方式,只是我们基于这个扩展包可以快速入门,免去很多不必要的配置和整合操作,你可以将其看作套在 Swoole 之上的一层壳,或者一个代理,真正提供服务的还是底层的 Swoole。

安装配置 LaravelS

在 Laravel 应用中使用 Swoole 之前,先通过 Composer 安装 LaravelS 扩展包:

composer require "hhxsv5/laravel-s:~3.3" -vvv

该扩展包具备自动发现功能(Laravel 5.5 以上版本可用),无需手动在 config/app.php 配置文件中注册,安装完成后,运行如下 Artisan 命令相应脚本和配置文件发布到根目录下:

php artisan laravels publish

该命令会发布配置文件 laravels.phpconfig 目录下,以及脚本文件到 bin 目录下:

你可以在配置文件中对 Swoole 进行一些基本配置,而脚本文件主要用于管理 Swoole 服务的启动、重载、关闭等操作。

启动 LaravelS

完成上述操作后,就可以通过 php bin/laravels start 命令启动 LaravelS 了:

这样,Swoole 服务就被启动起来,监听本地的 5200 端口,如果有请求发送到这个端口,它就可以进行处理。

此外 php bin/laravels 还支持其它命令对 LaravelS 进行管理:

通过 Supervisor 管理 LaravelS

如果是在生产环境使用,推荐使用 Supervisor 对 LaravelS 服务进行管理,从而提供服务的稳定性,相应的配置示例如下:

[program:laravel-s-test]
command=/user/local/bin/php /path/to/project/bin/laravels start -i
numprocs=1
autostart=true
autorestart=true
startretries=3
user=www-data
redirect_stderr=true
stdout_logfile=/path/to/project/storage/logs/supervisord-stdout.log

其中 /path/to/project 为 Web 项目的目录,你可以根据自己的项目路径进行修改。

基于 LaravelS 构建 HTTP 服务器

这里我们以 Laradock + Nginx 为例,进行示例演示,使用 Apache 作为 Web 服务器的话可以参考官方文档

配置 Nginx

我们知道在使用 Nginx 作为 Web 服务器的时候,前端资源文件,比如 CSS、JS、图片等静态资源都是通过 Nginx 进行处理的,比较高效,而 PHP 脚本请求这种动态资源都是转发到后端 PHP-FPM 进程进行处理,如果要基于 Swoole 实现高性能 HTTP 服务器,则这个 HTTP 服务器替代的也是 PHP-FPM 的职能,也就是说,我们将原本转发到 PHP-FPM 进程的请求转发给 Swoole 进行处理。在本例中,就是转发给 LaravelS 服务。

为此,我们在 Nginx 中新增一个站点配置 blog-s.conf,编写示例配置如下:

upstream laravels {
    # Connect IP:Port
    server workspace:5200 weight=5 max_fails=3 fail_timeout=30s;
    keepalive 16;
}
server {
    listen 80;

    server_name blog-s.test;
    root /var/www/blog/public;
    index index.php index.html index.htm;

    # Nginx 处理静态资源,LaravelS 处理动态资源
    location / {
        try_files $uri @laravels;
    }

    location @laravels {
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Real-PORT $remote_port;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header Scheme $scheme;
        proxy_set_header Server-Protocol $server_protocol;
        proxy_set_header Server-Name $server_name;
        proxy_set_header Server-Addr $server_addr;
        proxy_set_header Server-Port $server_port;
        proxy_pass http://laravels;
    }
}

然后我们配置一个虚拟域名 blog-s.test

配置 Laravel 应用

接下来,在 blog 项目根目录下打开 .env,新增下面两条配置:

LARAVELS_LISTEN_IP=workspace
LARAVELS_DAEMONIZE=true

LARAVELS_LISTEN_IP 用于设置 LaravelS 监听的 IP 地址,这里的地址和 Nginx 配置转发的 IP 地址保持一致,就是 workspace 容器名,LARAVELS_DAEMONIZE 用于设置后台启动 LaravelS 服务。

最后重新构建并重启 Laradock 相关服务:

docker-compose build workspace nginx
docker-compose down
docker-compose up -d nginx mysql redis memcached

然后进入 workspace 所在容器,到 blog 项目目录下运行 php bin/laravels start 启动 LaravelS 后端服务,此时,该服务会在后端运行:

访问基于 LaravelS 驱动的应用

在浏览器中访问 http://blog-s.test/,可以正常访问:

性能对比测试

本篇教程最高潮的部分来了。下面我们通过压力测试工具 ab 分别对基于 PHP-FPM 和 LaravelS(Swoole) 驱动的应用进行性能对比测试,两者共享同一份项目代码,都是基于 Laradock 环境,除了处理后端请求的服务不同之外,运行环境完全一致。

首先来看基于 PHP-FPM 的 blog.test,我们假设总请求数是 100,并发数是 10,运行结果如下:

返回的数据很多,核心关注的是每秒请求数(Requests per second),基于 PHP-FPM 驱动的博客应用首页每秒仅支持 2.28 个请求,下面再看看基于 Swoole 驱动的 blog-s.test,测试条件完全一样:

可以看到其每秒支持的请求数是 20.24,即每秒可处理20个请求,是前者的 10 倍!真是没有对比就没有伤害。。。

当然,这仅仅是在本地开发环境进行的简单测试,线上生产环境数据可能会有出入,但总体来说,基于 Swoole 的后端 HTTP 服务器性能更好是毋庸置疑的。

学院君 has written 1178 articles

Laravel学院院长,终身学习者

积分:151822 等级:P12 职业:手艺人 城市:杭州

6 条回复

  1. Hankin Hankin says:

    运行laravels时报错:Call to undefined function Hhxsv5\LaravelS\Illuminate\swoole_version() 开发环境是windows.

登录后才能进行评论,立即登录?