使用 Swoole 来加速 Laravel 应用

Laravel tytrock ⋅ 于 2019-10-26 18:49:00 ⋅ 3068 阅读

67O4dCaV0z.png

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 操作

67O4dCaV0z.png

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



是什么限制Laravel框架的速度?

Laravel框架启动的时候需要加载很多文件,再加上其出了名的生态环境好,所以在开发过程中我们就会发现有非常多的已经造好的轮子,这也就使得Laravel的一次启动的磁盘IO特别高(就是要加载很多文件嘛),文章:Laravel5框架性能优化技巧中也提到过一些优化,但是并没有实质的解决磁盘IO高的问题。


既然已经知道了问题所在,那就很容易解决了,只要每次启动Laravel的时候不都重新加载这些文件就好了,这时候大名鼎鼎的swoole就登场了。


安装swooletw/laravel-swoole

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

  • 在 Swoole 运行 Laravel/Lumen 应用

  • 出色的性能提升至 30x

  • 沙盒模式隔离应用程序容器

  • 支持在 Laravel 应用中运行 WebSocket 服务器

  • 支持 Socket.io 协议

  • 支持 Swoole 表跨进程共享

使用 Composer 安装:

composer require swooletw/laravel-swoole

这个包依赖于 Swoole 。在使用这个包之前,请确保你的机器安装了正确的 Swoole 。CentOS 下 PHP 安装 Swoole 的支持

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

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


然后,添加服务提供者,在 config/app.php 服务提供者数组添加该服务提供者:

 Laravel 下

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

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

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

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


将配置文件导出到config文件夹下

php artisan vendor:publish --provider="SwooleTW\Http\HttpServiceProvider"



建立并运行起来

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

 php artisan swoole:http start|stop|restart|reload 

依次是,启动/停止/重启/重载


php artisan swoole:http start

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

image.png


注意:该拓展是不支持热启动的,所以每次有代码更新都要重启服务 php artisan swoole:http restart 。当然你也可以在linux上写一个脚本,让 git pull 代码后自动重启服务。


使用Nginx代理

swoole在官网也提到过:swoole_http_server对Http协议的支持并不完整,建议仅作为应用服务器。并且在前端增加Nginx作为代理。

那么,我们就增加需要配置nginx.conf里的server:

 server {
  listen        80;
  server_name   yourdomain.com;
  root          /path/to/web/public;
  index         index.php index.html;


  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 $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;
    }
}


本帖已被设为精华帖!
回复数量: 0
    暂无评论~~
    • 请注意单词拼写,以及中英文排版,参考此页
    • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
    • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
    • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
    • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
    Ctrl+Enter