使用 swoole 加速 Laravel5.6 Restful API 接口
5

  1. 创建自定义artisan命令
    php artisan make:command SwooleServer //默认在app/Console/Commans目录下创建SwooleServer.php文件。可借鉴我的上一遍文章Laravel 5.6 中优雅的管理 swoole 进程代码如下:

        <?php
    
        namespace App\Console\Commands;
        use Illuminate\Console\Command;
        use Illuminate\Support\Facades\App;
    
        class SwooleServer extends Command
        {
            //swoole http server instance
            private $server;
    
            //进程ID
            private $pid_file;
    
            //日志文件
            private $log_file;
    
            /**
             * The name and signature of the console command.
             *
             * @var string
             */
            protected $signature = 'swoole {action}';
    
            /**
             * The console command description.
             *
             * @var string
             */
            protected $description = 'start or stop the swoole http server';
    
            /**
             * Create a new command instance.
             *
             * @return void
             */
            public function __construct()
            {
                parent::__construct();
                //指定主进程PID存储文件
                $this->pid_file = __DIR__ . '/../../../storage/swoole_server.pid';
                //日志文件存储
                $this->log_file = __DIR__ . '/../../../storage/logs/' . date('Ymd') . '_swoole_server.log';
                if (!is_file($this->log_file)) {
                    $resource = fopen($this->log_file, "w");
                    fclose($resource);
                }
            }
    
            /**
             * Execute the console command.
             *
             * @return mixed
             */
            public function handle()
            {
                //获取传递的操作
                $arg = $this->argument('action');
    
                switch ($arg) {
                    case 'start':
                        //检测进程是否已开启
                        $pid = $this->getPid();
                        if ($pid && \Swoole\Process::kill($pid, 0)) {
                            $this->error("\r\nswoole http server process already exist!\r\n");
                            exit;
                        }
    
                        $this->server = new \Swoole\Http\Server("0.0.0.0", 9501);
                        $this->server->set([
                            'worker_num' => 8,
                            'daemonize' => 1,
                            'max_request' => 1000,
                            'dispatch_mode' => 2,
                            'pid_file' => $this->pid_file,
                            'log_file' => $this->log_file,
                            'log_level' => 3, //日志等级 notice
                        ]);
    
                        //绑定操作类回调函数
                        $app = App::make('App\Handles\SwooleServerHandle');
    
                        $this->server->on('workerstart', array($app, 'onWorkerStart'));
                        $this->server->on('request', array($app, 'onRequest'));
    
                        $this->info("\r\nswoole http server process created successful!\r\n");
    
                        $this->server->start();
                        break;
    
                    case 'stop':
                        if (!$pid = $this->getPid()) {
                            $this->error("\r\nswoole http server process not started!\r\n");
                            exit;
                        }
                        if (\Swoole\Process::kill((int)$pid)) {
                            $this->info("\r\nswoole http server process close successful!\r\n");
                            exit;
                        }
                        $this->info("\r\nswoole http server process close failed!\r\n");
                        break;
    
                    default:
                        $this->error("\r\noperation method does not exist!\r\n");
                }
    
            }
    
            //获取pid
            private function getPid()
            {
                return file_exists($this->pid_file) ? file_get_contents($this->pid_file) : false;
            }
        }
  2. 编写操作类SwooleServerHandle

     <?php
    /**
     * Created by PhpStorm.
     * User: kite
     */
    
    namespace App\Handles;
    
    class SwooleServerHandle
    {
        //header Server 全局变量的映射关系
        private static $headerServerMapping = [
            'x-real-ip'       => 'REMOTE_ADDR',
            'x-real-port'     => 'REMOTE_PORT',
            'server-protocol' => 'SERVER_PROTOCOL',
            'server-name'     => 'SERVER_NAME',
            'server-addr'     => 'SERVER_ADDR',
            'server-port'     => 'SERVER_PORT',
            'scheme'          => 'REQUEST_SCHEME',
        ];
    
        public function onWorkerStart($serv,$worker_id)
        {
            require __DIR__.'/../../vendor/autoload.php';
            require_once __DIR__.'/../../bootstrap/app.php';
        }
    
        public function onRequest($request,$response)
        {
            //server信息
            $_SERVER =[];
            if (isset($request->server)) {
                foreach ($request->server as $k => $v) {
                    $_SERVER[strtoupper($k)] = $v;
                }
            }
    
            //header头信息
            if (isset($request->header)) {
                foreach ($request->header as $key => $value) {
                    if (isset(self::$headerServerMapping[$key])) {
                        $_SERVER[self::$headerServerMapping[$key]] = $value;
                    } else {
                        $key = str_replace('-', '_', $key);
                        $_SERVER[strtoupper('http_' . $key)] = $value;
                    }
                }
            }
            //是否开启https
            if (isset($_SERVER['REQUEST_SCHEME']) && $_SERVER['REQUEST_SCHEME'] === 'https') {
                $_SERVER['HTTPS'] = 'on';
            }
            //request uri
            if (strpos($_SERVER['REQUEST_URI'], '?') === false && isset($_SERVER['QUERY_STRING']) && strlen($_SERVER['QUERY_STRING']) > 0
            ) {
                $_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
            }
    
            //全局的
            if (!isset($_SERVER['argv'])) {
                $_SERVER['argv'] = isset($GLOBALS['argv']) ? $GLOBALS['argv'] : [];
                $_SERVER['argc'] = isset($GLOBALS['argc']) ? $GLOBALS['argc'] : 0;
            }
    
            //get信息
            $_GET = [];
            if (isset($request->get)) {
                foreach ($request->get as $k => $v) {
                    $_GET[$k] = $v;
                }
            }
    
            //post信息
            $_POST = [];
            if (isset($request->post)) {
                foreach ($request->post as $k => $v) {
                    $_POST[$k] = $v;
                }
            }
    
            //文件请求
            $_FILES =[];
            if (isset($request->files)) {
                foreach ($request->files as $k => $v) {
                    $_FILES[$k] = $v;
                }
            }
            //cookie
            $_COOKIE=[];
            if (isset($request->cookie)) {
                foreach ($request->cookie as $k => $v) {
                    $_COOKIE[$k] = $v;
                }
            }
    
            ob_start();//启用缓存区
            \Illuminate\Http\Request::enableHttpMethodParameterOverride();
            $kernel = app()->make(\Illuminate\Contracts\Http\Kernel::class);
            $laravelResponse = $kernel->handle(
                //Create an Illuminate request from a Symfony instance.
                $request =  \Illuminate\Http\Request::createFromBase(new \Symfony\Component\HttpFoundation\Request($_GET, $_POST, [], $_COOKIE, $_FILES, $_SERVER, $request->rawContent()))
            );
    
            $laravelResponse->send();
            $kernel->terminate($request, $laravelResponse);
            $res = ob_get_contents();//获取缓存区的内容
            ob_end_clean();//清除缓存区
            //输出缓存区域的内容
            $response->end($res);
        }
    }

3.使用php artisan swoole start即可开启服务,在nginx配置代理即可加速你的Restful api接口.
4.在centos7 单核 2G内存下的测试结果如下:
未使用swoole的吞吐量只有2.44
file
使用了swoole的吞吐量提升到了56.19且加大并发数吞吐量都可以维持一个水平
file

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 4

每次修改代码貌似要重启进程

1天前

@lovecn 是的,就这两个文件写的比较简单

1天前

使用 swoole 加速 lumen 不成功 。。

1天前

@Cium_ 这个没在lumen上测试过,我在同一个虚拟中的测试结果可有提升25倍左右吞吐

22小时前

  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
  请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!