laravel 使用workerman提供http服务
- 背景
公司项目使用的是laravel框架,开发完后压测一直不过,期间开启过opcache扩展加速(不属于本篇内容,不在此赘述),后决定采用workerman或swoole加速laravel应用,本篇以workerman为例。
首先大家应该知道laravel每次收到请求都会把框架核心代码加载一遍,使用workerman提升性能的关键是把框架核心代码缓存起来,这样就不需要每次重新加载了,以此来提升性能(swoole同理)
- composer安装workerman
#更改composer源
composer config -g repo.packagist composer https://packagist.phpcomposer.com
#下载workerman包
composer require workerman/workerman
- 创建启动命令
- 生成 WorkermanCommand 文件
php artisan make:command WorkermanCommand
执行以上命令行会在 app/Console/Commands/ 目录下生成 WorkermanCommand.php 文件,对文件做如下修改。
<?php
namespace App\Console\Commands;
use Workerman\Worker;
use Illuminate\Console\Command;
class WorkermanCommand extends Command
{
private $server;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'wk {action}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Start a Workerman server.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
global $argv;
$arg = $this->argument('action');
$argv[1] = $argv[2];
$argv[2] = isset($argv[3]) ? "-{$argv[3]}" : '';
switch ($arg) {
case 'start':
$this->start();
break;
case 'stop':
break;
case 'restart':
break;
case 'reload':
break;
case 'status':
break;
case 'connections':
break;
}
}
private function start()
{
// 创建一个Worker监听20002端口,不使用任何应用层协议
$this->server = new Worker("http://0.0.0.0:1234");
// 启动4个进程对外提供服务
$this->server->count = 4;
$handler = \App::make('handlers\WorkermanHandler');
// 连接时回调
$this->server->onConnect = [$handler, 'onConnect'];
// 收到客户端信息时回调
$this->server->onMessage = [$handler, 'onMessage'];
// 进程启动后的回调
$this->server->onWorkerStart = [$handler, 'onWorkerStart'];
// 断开时触发的回调
$this->server->onClose = [$handler, 'onClose'];
// 运行worker
Worker::runAll();
}
}
在这个自定义命令还引用了其他的类文件,如
$handler = \App::make('handlers\WorkermanHandler');
所以,需要创建一个 WorkermanHandler.php
的文件来处理对应的操作
2、创建 WorkermanHandler.php
创建 app/handlers/WorkermanHandler.php
<?php
namespace handlers;
class WorkermanHandler
{
public function onWorkerStart($worker)
{
//加载index文件的内容
require __DIR__ . '/../../vendor/autoload.php';
require_once __DIR__ . '/../../bootstrap/app.php';
}
// 处理客户端连接
public function onConnect($connection)
{
echo "new connection from ip " . $connection->getRemoteIp() . "\n";
}
// 处理客户端消息
public function onMessage($connection, $data)
{
// 向客户端发送hello $data
//server信息
if (isset($data->server)) {
foreach ($data->server as $k => $v) {
$_SERVER[strtoupper($k)] = $v;
}
}
//header头信息
if (isset($data->header)) {
foreach ($data->header as $k => $v) {
$_SERVER[strtoupper($k)] = $v;
}
}
//get请求
if (isset($data->get)) {
foreach ($data->get as $k => $v) {
$_GET[$k] = $v;
}
}
//post请求
if (isset($data->post)) {
foreach ($data->post as $k => $v) {
$_POST[$k] = $v;
}
}
//文件请求
if (isset($data->files)) {
foreach ($data->files as $k => $v) {
$_FILES[$k] = $v;
}
}
//cookies请求
if (isset($data->cookie)) {
foreach ($data->cookie as $k => $v) {
$_COOKIE[$k] = $v;
}
}
ob_start();//启用缓存区
//加载laravel请求核心模块
$kernel = app()->make(\Illuminate\Contracts\Http\Kernel::class);
$laravelResponse = $kernel->handle(
$request = \Illuminate\Http\Request::capture()
);
$laravelResponse->send();
$kernel->terminate($request, $laravelResponse);
$res = ob_get_contents();//获取缓存区的内容
ob_end_clean();//清除缓存区
//输出缓存区域的内容
$connection->send($res);
}
// 处理客户端断开
public function onClose($connection)
{
echo "connection closed from ip {$connection->getRemoteIp()}\n";
}
}
3.使用composer自动加载
"classmap": [
"app/Handlers"
],
执行
composer dump-autoload -o
至此基本配置写完了,下边试试启动一下
php artisan wk start
----------------------------------------- WORKERMAN -----------------------------------------
Workerman version:3.5.19 PHP version:7.2.11
------------------------------------------ WORKERS ------------------------------------------
proto user worker listen processes status
tcp xuce none http://0.0.0.0:1234 4 [OK]
---------------------------------------------------------------------------------------------
说明启动成功了!!!