基于 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
该扩展包具备自动发现功能(Laravel 5.5 以上版本可用),无需手动在 config/app.php
配置文件中注册,安装完成后,运行如下 Artisan 命令相应脚本和配置文件发布到根目录下:
php artisan laravels publish
该命令会发布配置文件 laravels.php
到 config
目录下,以及脚本文件到 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 服务器性能更好是毋庸置疑的。
35 Comments
都启动了,就是报这个错[error] 11#11: *75 connect() failed (111: Connection refused) while connecting to upstream, client: 102.164.197.200, server: , request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:5200/", host: "94.191.20.106:80
学院君,你好, 我按照文章中设置了nginx之后,报的也是502错误, [error] 11#11: *75 connect() failed (111: Connection refused) while connecting to upstream, workspace容器中swoole http启动了,nginx workspace也重启了, 还是报502错误. 我的系统是 macOS 10.13.6
如何清空配置缓存
更改后上传视频好像 上传超过2M就报 413 Request Entity Too Large
更改后上传视频好像 上传超过2M就报 413 Request Entity Too Large
问一下 之前有个 laravel-swoole 和这个laravels有什么区别 是同样的功能吗 哪个更好
laravel-swoole 和这个laravels都不支持dingoapi? 项目运行后,为什么数据库内容更新了,在laravels里还是旧的数据,科普科普
在下同样也遇到了一样的错误,直接127.0.0.1:5200访问没问题,但配合Nginx仿教程配置后就介样了,请问你后来有解决问题吗?
laravelS有些问题可能跟laravel有出入。测试注册登入再到退出登入,缓存没有销毁,程序已经退出成功,数据库内也销毁数据了,可是页面上还显示登入成功以及登入的信息(在数据库以及删除此条信息了)。