使用 Swoole 来加速你的 Laravel 应用

file

Swoole 是为 PHP 开发的生产级异步编程框架。 他是一个纯 C 开发的扩展, 他允许 PHP 开发者在 PHP 中写 高性能,可扩展的并发 TCP, UDP, Unix socket, HTTP, WebSocket 服务, 而不需要拥有太多的非阻塞 I/O 编程和低级别的 Linux 内核知识。 你可以把 Swoole 想象成 NodeJS, 但对于 PHP 来说将有更高性能。

为什么要在 Swoole 上运行 Laravel?

下图展示了 PHP 的生命周期。正如你所看到的那样,当你每次运行 PHP 脚本的时候,PHP都需要初始化模块并为你的运行环境启动Zend引擎。并且将 PHP 脚本编译为 OpCodes 以便 Zend引擎执行。

但是, 这样的生命周期需要在每次请求的时候都执行一遍。因为单个请求创建的环境在请求执行结束后会立即销毁。

换句话说, 在传统的 PHP 生命周期中, 为了脚本执行而浪费了大量的时间去创建和销毁资源。想象一下像 Laravel 这样的框架, 在每次请求中需要加载多少文件? 同时也浪费了大量的 I/O 操作
file

因此如果我们利用 Swoole 内置一个应用级别的 Server, 并且所有脚本文件在加载一次之后便可以保存在内存中呢? 这就是为什么我们需要尝试在 Swoole 上运行 Laravel。 Swoole 可以提供强大性能而 Laravel 则可以提供优雅代码结构使用。这俩儿真是完美组合 !

安装

以下是 swooletw/laravel-swoole 的主要特点:

  • 在 Swoole 运行 Laravel/Lumen 应用
  • 出色的性能提升至 30x
  • 沙盒模式隔离应用程序容器
  • 支持在 Laravel 应用中运行 WebSocket 服务器
  • 支持 Socket.io 协议
  • 支持 Swoole 表跨进程共享

使用 Composer 安装:

$ composer require swooletw/laravel-swoole

这个包依赖于 Swoole 。在使用这个包之前,请确保你的机器安装了正确的 Swoole 。使用下面的命令快速安装(linux):

pecl install swoole

在安装这个扩展之后,你需要编辑 php.ini 添加  extension=swoole.so

php -i | grep php.ini                      # check the php.ini file location
sudo echo "extension=swoole.so" >> php.ini  # add the extension=swoole.so to the end of php.ini
php -m | grep swoole                       # check if the swoole extension has been enabled

访问 官网 获取更多的信息。

注意:Swoole 现在只支持 Linux 和 OSX 。Windows 服务器现在还不支持。

然后,添加服务提供者:

如果你使用 Laravel ,在 config/app.php 服务提供者数组添加该服务提供者:

[
    'providers' => [
        SwooleTW\Http\LaravelServiceProvider::class,
    ],
]

如果你使用 Lumen ,请将下面的代码添加到 bootstrap/app.php

$app->register(SwooleTW\Http\LumenServiceProvider::class);

这个包支持包自动发现机制。如果你运行 Laravel 5.5 以上版本,你可以跳过这一步。

建立并运行起来

现在,你可以执行以下的命令来启动 Swoole HTTP 服务。

$ php artisan swoole:http start

然后你可以看到以下信息:

Starting swoole http server...
Swoole http server started: <http://127.0.0.1:1215>

现在可以通过访问 http://127.0.0.1:1215 来进入 Laravel 应用。

基准测试

使用 MacBook Air 13寸(2015年产)及干净的 Lumen 5.5 项目测试:
基准测试工具: wrk

wrk -t4 -c100 http://your.app

基于 FPM 的 Nginx

Running 10s test @ http://lumen.app:9999
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.14s   191.03ms   1.40s    90.31%
    Req/Sec    22.65     10.65    50.00     65.31%
  815 requests in 10.07s, 223.65KB read
Requests/sec:     80.93
Transfer/sec:     22.21KB

Swoole HTTP 服务

Running 10s test @ http://127.0.0.1:1215
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    11.58ms    4.74ms  68.73ms   81.63%
    Req/Sec     2.19k   357.43     2.90k    69.50%
  87879 requests in 10.08s, 15.67MB read
Requests/sec:   8717.00
Transfer/sec:      1.55MB

更多信息

在 Github Repo 查看官方包, 也可以参考 官方文档 获取更多信息。

此文最初发表于 Laravel News

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://laravel-news.com/laravel-swoole?

译文地址:https://learnku.com/php/t/10939/use-swoo...

本帖已被设为精华帖!
本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
讨论数量: 37
Summer

@好好先森V5
@albert_chen 说在前面,两位的项目都很赞,也都很大方地使用了 MIT License 进行开源,我很敬佩两位。

@albert_chen 文档参照了人家的,很正常嘛。而 @好好先森V5 不悦,换位思考,理解下对方啦。互相借鉴,才会有成长,感激他的成果的话,在 readme 里给个 ## Thinks to 也可。

@好好先森V5 既然已经使用了 MIT License,别人参考了下你的架构和文档,也未尝不可哈。

我认为,大家一起构建一个 积极的互助的 生态圈才是最重要的,因为这样我们才能有更多的人参与进来和更多的优质项目,最终受益的人都是我们每一个个体。我建议两位都在互相的文档里链接对方的项目,如 Spatie 经常在他们的项目 Readme 里加一个 Alternatives 区块,社区里认同的同学给我点个赞 :+1:

file

@duck0026
@Littlesqx

5年前 评论
wenber

使用Nginx来代理运行于Swoole上的Laravel

server {
    listen 80;
    server_name your.domain.com;
    root /path/to/laravel/public;
    index index.php;
    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 "/";
        }
        proxy_set_header Host $host;
        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;
        # IF https
        # proxy_set_header HTTPS "on";
        proxy_pass http://127.0.0.1:1215$suffix;
    }
}
5年前 评论
php -i | grep php.ini                      # check the php.ini file location
sudo echo "extension=swoole.so" > php.ini  # add the extension=swoole.so to the end of php.ini
php -m | grep swoole                       # check if the swoole extension has been enabled

应该是这个,用上面直接把配置文件覆盖掉了:

sudo echo "extension=swoole.so" >> php.ini 
5年前 评论

@好好先森V5 您好,我是 laravel-swoole 的開發者 Albert,對於您提出的文檔對照,我承認該部分的文檔內容的確我是參照自您的專案文檔,若是這部分讓您不悅我願意向您致歉,或是您要讓我更正裡面任何文字也請告知,我這裡必定盡力配合。

但是如果您或是其他網友有分析過兩份專案的源代碼就會發現架構上有根本性很大的不同,"終於知道為什麼似曾相識"這句話似乎企圖誘導其他不了解的人認為我的專案是抄襲您的專案而來。

雖然說利用 Swoole 來加速 Laravel 這個概念上實作方法大方向差異不會太大,但無論是您或是我的專案也都不是第一個嘗試這樣做的人,而且兩邊專案目前發展方向也有所不同,想在此特別澄清,如果有比較過兩專案的建立時間還會發現我的時間是更早的。

附上我這裡專案完整的文檔:https://github.com/swooletw/laravel-swoole...,有興趣的人仔細讀完之後便會了解我前面所說,您如果對於我文檔任何篇章覺得有可取之處,歡迎直接取用,也歡迎您可以使用我這邊專案的源代碼或任何觀念,反正專案本來就是基於 MIT 授權,我完全不會計較的。

另外我在其他介紹我專案項目的文章留言處也有發現您的蹤跡,發現您對於名聲似乎有一份執著在,我並不想特別與您競爭什麼,只是繼續發展我自己想投入的項目上而已。
http://www.cnblogs.com/johnson108178/p/810...
https://twitter.com/laravelnews/status/992...

以上說明,不會再繼續針對任何底下的留言進行回覆,清者自清,我來繼續寫程式了。

5年前 评论

@albert_chen
Take easy 你理解的太严重了!

  • 我阐述了疑惑,你解答了,OK,那算完事。
  • 同属于Swoole生态,百花齐放是好事,期待你更加出色的项目。
5年前 评论
php -i | grep php.ini                      # check the php.ini file location
sudo echo "extension=swoole.so" > php.ini  # add the extension=swoole.so to the end of php.ini
php -m | grep swoole                       # check if the swoole extension has been enabled

应该是这个,用上面直接把配置文件覆盖掉了:

sudo echo "extension=swoole.so" >> php.ini 
5年前 评论

进来学习下..正好最近要搞swoole

5年前 评论
wenber

使用Nginx来代理运行于Swoole上的Laravel

server {
    listen 80;
    server_name your.domain.com;
    root /path/to/laravel/public;
    index index.php;
    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 "/";
        }
        proxy_set_header Host $host;
        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;
        # IF https
        # proxy_set_header HTTPS "on";
        proxy_pass http://127.0.0.1:1215$suffix;
    }
}
5年前 评论

@好好先森V5 您好,我是 laravel-swoole 的開發者 Albert,對於您提出的文檔對照,我承認該部分的文檔內容的確我是參照自您的專案文檔,若是這部分讓您不悅我願意向您致歉,或是您要讓我更正裡面任何文字也請告知,我這裡必定盡力配合。

但是如果您或是其他網友有分析過兩份專案的源代碼就會發現架構上有根本性很大的不同,"終於知道為什麼似曾相識"這句話似乎企圖誘導其他不了解的人認為我的專案是抄襲您的專案而來。

雖然說利用 Swoole 來加速 Laravel 這個概念上實作方法大方向差異不會太大,但無論是您或是我的專案也都不是第一個嘗試這樣做的人,而且兩邊專案目前發展方向也有所不同,想在此特別澄清,如果有比較過兩專案的建立時間還會發現我的時間是更早的。

附上我這裡專案完整的文檔:https://github.com/swooletw/laravel-swoole...,有興趣的人仔細讀完之後便會了解我前面所說,您如果對於我文檔任何篇章覺得有可取之處,歡迎直接取用,也歡迎您可以使用我這邊專案的源代碼或任何觀念,反正專案本來就是基於 MIT 授權,我完全不會計較的。

另外我在其他介紹我專案項目的文章留言處也有發現您的蹤跡,發現您對於名聲似乎有一份執著在,我並不想特別與您競爭什麼,只是繼續發展我自己想投入的項目上而已。
http://www.cnblogs.com/johnson108178/p/810...
https://twitter.com/laravelnews/status/992...

以上說明,不會再繼續針對任何底下的留言進行回覆,清者自清,我來繼續寫程式了。

5年前 评论

两方格局似乎高下立见呢...

5年前 评论

@albert_chen
Take easy 你理解的太严重了!

  • 我阐述了疑惑,你解答了,OK,那算完事。
  • 同属于Swoole生态,百花齐放是好事,期待你更加出色的项目。
5年前 评论
Summer

@好好先森V5
@albert_chen 说在前面,两位的项目都很赞,也都很大方地使用了 MIT License 进行开源,我很敬佩两位。

@albert_chen 文档参照了人家的,很正常嘛。而 @好好先森V5 不悦,换位思考,理解下对方啦。互相借鉴,才会有成长,感激他的成果的话,在 readme 里给个 ## Thinks to 也可。

@好好先森V5 既然已经使用了 MIT License,别人参考了下你的架构和文档,也未尝不可哈。

我认为,大家一起构建一个 积极的互助的 生态圈才是最重要的,因为这样我们才能有更多的人参与进来和更多的优质项目,最终受益的人都是我们每一个个体。我建议两位都在互相的文档里链接对方的项目,如 Spatie 经常在他们的项目 Readme 里加一个 Alternatives 区块,社区里认同的同学给我点个赞 :+1:

file

@duck0026
@Littlesqx

5年前 评论
Summer

@好好先森V5
@albert_chen 都是误会,不提也罢哈

5年前 评论

Hi @Summer , 感謝您的解說與回覆,我認為您提的 Alternatives 區塊概念很好,我願意加上 @好好先森V5 項目的連結表示致意

另外我其實也相當認同 @好好先森V5 專案中的許多代碼實踐,可能是我過度理解了,既是誤會,解開也就沒事了,也期待能與您在 Laravel 整合方面有其他的交流

5年前 评论

看来是我多嘴了 :joy:

5年前 评论

@albert_chen 如何支持dingo/api的路由呢。二个包都封装了laravel的request和response...

5年前 评论
阿麦

这个包很好用我自己也在用,但是 session 会出问题 目前不知道怎么解决

5年前 评论
李铭昕

支持协程么

5年前 评论

按照文档配置了swool,nginx配置文件,https://github.com/swooletw/laravel-swoole... 但是网站所有链接都指向首页,
file

这里修改为
proxy_pass http://127.0.0.1:1215$suffix;
问题解决。

5年前 评论
1234561212122121121212

好像不能使用dd,报错500,但是日志不会记录

5年前 评论

swooleTW的lock怎么使用

file
第一个进程访问的时候,我故意放一个timer_after阻塞一下,10秒后会unlock。
然后第二个进程访问的时候,就直接卡住了,然后time out。。请问这样使用正确吗。@albert_chen @Summer

5年前 评论

各位好, 謝謝大家使用這個 package,因為我個人比較少造訪這個網站,也為了大家的問題能夠得到妥善的答覆,還麻煩各位至 Github 上依照格式直接開 issue(請各位盡量能使用英文,這樣可以讓更多不同國家的人一同參與討論),我看到 issue 有空就會回覆,再次謝謝大家的配合 :)

5年前 评论

不知道是不是我的测试方法有问题,本人测试的结果是使用 swoole http 服务 和 开启 opcache 的效果(请求耗时)基本一致
下面是一些测试结果:
file
测试的环境是 1核1G 阿里云,php7.1.7
本人本地 ab 测试的时候,数据也是非常的好看的,上面的测试结果是阿里云的 PTS 测的

5年前 评论
fatrbaby

有上生产环境的么?

5年前 评论

@ruby 加速php运行原理上,我也感觉是一样的,都是缓存PHP文件,下次运行时调用内存里的文件。

5年前 评论

测试了几天,高并发应用用着挺好,但是涉及到高运算的时候,慢的要命。

5年前 评论
    • 感觉和慕课网的singwa老师讲的好像。。 :+1:
5年前 评论

@albert_chen
关于贵项目中的配置 swoole_http.php

  • pre_resolved
  • instances
  • providers

的作用,经过测验和里面的注释有出入。可以写的再具体点吗?

file

5年前 评论

@albert_chen I am sorry to say why not use simplified Chinese?

4年前 评论
小帅 4年前

请问:按照教程装好后,使用wrk进行测试得到的结果却不同,swoole的性能比Apache的性能差,是因为测试的方式不对还是有什么配置没安装的?以下是测试结果

使用MacBook Pro (Retina, 15-inch, Mid 2015)以及干净的laravel5.8框架测试

Apache

$ wrk -t4 -c100 http://laravel5.8.localhost
Running 10s test @ http://laravel5.8.localhost
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    92.36ms  177.32ms   2.00s    90.54%
    Req/Sec   109.91     76.84   565.00     74.47%
  3717 requests in 10.11s, 11.55MB read
  Socket errors: connect 0, read 0, write 0, timeout 106
Requests/sec:    367.76
Transfer/sec:      1.14MB

$ brew info httpd
httpd: stable 2.4.39 (bottled)
Apache HTTP server

Swoole

$ wrk -t4 -c100 http://127.0.0.1:1215
Running 10s test @ http://127.0.0.1:1215
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   301.45ms  482.05ms   1.63s    80.44%
    Req/Sec    35.65     95.76   435.00     93.65%
  290 requests in 10.17s, 0.89MB read
  Socket errors: connect 0, read 0, write 0, timeout 19
Requests/sec:     28.53
Transfer/sec:     89.61KB

$ php --ri swoole

swoole

Swoole => enabled
Author => Swoole Team <team@swoole.com>
Version => 4.3.4
Built => May 21 2019 19:18:25
coroutine => enabled
kqueue => enabled
rwlock => enabled
http2 => enabled
pcre => enabled
zlib => enabled
brotli => enabled
async_redis => enabled

Directive => Local Value => Master Value
swoole.enable_coroutine => On => On
swoole.display_errors => On => On
swoole.use_shortname => On => On
swoole.unixsock_buffer_size => 262144 => 262144
4年前 评论

//检测是否微信中打开
function is_weichat(){
echo '

';
print_r($_SERVER);exit;
$ua = $_SERVER['HTTP_USER_AGENT'];//发现一个致命的问题,这个方式不能用,
$isWebChat=1;//1是微信,2不是微信

if (strpos($ua, 'MicroMessenger') == false && strpos($ua, 'Windows Phone') == false)  $isWebChat=0;

//返回
return  $isWebChat;

}

4年前 评论

如何获得:HTTP_USER_AGENT ??????????????

4年前 评论

@gg22mm nginx配置中增加 underscores_in_headers on;,laravel代码中使用request()->header()获取

3年前 评论

laravel-admin不能正常访问了,样式错乱了

3年前 评论

我是用该套教程 发现 微信支付走不通了 查了一下问题是 wxApi中 $_SERVER['REMOTE_ADDR'] 这个方法失效了 请问 大佬怎么解决这个问题啊?

2年前 评论

基于laravel 7 + vue 上了swoole 发现有些接口JWTtoken 有些失败,有些成功。同一个接口都会出现一个验证成功一个验证失败的情况

2年前 评论
aiyisuimeng 2年前

authorization 找不到了 为什么

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!