larave octane 是什么
octane
是 laravel
官方提供的第三方包,它可以通过集成 Swoole
和 RoadRunner
这两种高性能的应用服务器来提高应用程序的性能。
RoadRunner
本身是一个用 Go
语言编写的开源 PHP
应用程序服务器。 Swoole
是一个使用 C++
语言编写的基于异步事件驱动和协程的并行网络通信引擎,为 PHP
提供协程、高性能网络编程支持。
与 Apache
或 Nginx
和 PHP-FPM
非常相似,HTTP
请求可以发送到 RoadRunner
或 Swoole
以执行 PHP
代码,然后将响应发送回。 RoadRunner
或 Swoole
的不同之处在于它可以将 PHP
运行中的应用程序保留在内存中,以便在应用程序启动后获得更快的速度。 对于 Laravel
来说,这是相当有帮助的。
环境要求
- PHP 8.0+
- Larave 8.35+
Swoole
和RoadRunner
必须在unix
系统下安装(macOS, linux, window(WSL2))RoadRunner
:请先确保curl
,zip
sockets
等 php 扩展已经安装- 本地虚拟机,IP:
192.168.2.11
安装历程
按照 Laravel
的官方文档来安装 Swoole
和 RoadRunner
第三方包是一件非常痛苦的事,因为安装的过程中经常会遇到乱七八糟的问题。为了减少大家走的弯路,所以我有必要在这里着重强调几个问题。
- 一定要在
unix
系统下安装,unix
系统包括macOS
linux
和windows的linux子系统
- 为了能够在本地能够访问虚拟机,请先关闭
linux
防火墙
Step1. 安装 octane
包
composer require laravel/octane
假设你已经有了新的 laravel
项目。进入项目根目录下执行以上命令。
Step2. 配置 nginx 代理
为什么要先配置 nginx 的代理?
官方文档 中说:
The Octane server can be started via the octane:start Artisan command. By default, this command will utilize the server specified by the server configuration option of your application's octane configuration file:
php artisan octane:start
By default, Octane will start the server on port 8000, so you may access your application in a web browser via http://localhost:8000.
意思是执行启动命令后,默认端口 8000
,在浏览器中可以通过 http://localhost:8000
访问。 但我通过 http://192.168.2.11:8000
却访问不了,知道这个问题原因的朋友可以留言告知下。
按照官方文档的 nginx
配置
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 8009; # 浏览器端访问的端口
#listen [::]:80;
server_name 127.0.0.1;
server_tokens off;
root /var/www/html/octane/public;
index index.php;
charset utf-8;
location /index.php {
try_files /not_exists @octane;
}
location / {
try_files $uri $uri/ @octane;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
access_log /var/log/nginx/octane-access.log main;
error_log /var/log/nginx/octane-error.log error;
error_page 404 /index.php;
location @octane {
set $suffix "";
if ($uri = /index.php) {
set $suffix ?$query_string;
}
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Scheme $scheme;
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;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://127.0.0.1:8010$suffix; # 代理请求
}
}
注意上面配置中注释的地方:
listen 8009
: 是我将要在浏览器中访问的端口http://192.168.2.11:8009
http://127.0.0.1:8010
: 是octane
启动时指定的端口
Step3. 使用 Swoole
1. 安装 Swoole
扩展
Octane
是依赖 Swoole
扩展的。php Swoole
扩展的安装大家从网上找些教程安装下就行。
2. 发布 octane
的配置文件
php artisan octane:install
此命令将会在 config
目录下生成 octane.php
的配置文件
3. 开启服务
php artisan octane:start --server=swoole --port=8010
输出:
INFO Server running…
Local: http://127.0.0.1:8010
Press Ctrl+C to stop the server
看到这些,说明 octane
已经成功启动了。
4. 浏览器中访问
因为我们刚才已经配置了 nginx
代理,只要在浏览器中输入 http://192.168.2.11:8009
并回车。
可以看到命令界面上会出现 GET
请求。
从上图可以看到,第一次请求用了 85.46ms,而从第二次之后只用了几毫秒,速度上有了极大的提升。
Step4. ab 压测
下面是虚拟机上的liunx系统的数据:
查看内核版本
[root@localhost ~]# uname -r 3.10.0-1160.41.1.el7.x86_64
查看 CPU
[root@localhost ~]# grep "model name" /proc/cpuinfo | cut -f2 -d: Intel(R) Core(TM) i5-10500 CPU @ 3.10GHz Intel(R) Core(TM) i5-10500 CPU @ 3.10GHz
查看 CPU 核数
[root@localhost ~]# cat /proc/cpuinfo |grep "cores"|uniq cpu cores : 2
查看内存
[root@localhost ~]# grep MemTotal /proc/meminfo | cut -f2 -d: 1863020 kB
Swoole 压测
1. 创建 users
表:
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`role` tinyint(3) unsigned NOT NULL DEFAULT '2' COMMENT '角色:1-管理员,2-会员...',
`created_at` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
`updated_at` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
`deleted_at` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '删除时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='会员表';
2. 修改配置文件
# .env
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=test
DB_USERNAME=root
DB_PASSWORD=123456
3. 生成控制器并编写代码
生成控制器
php artisan make:controller UserController
编写代码
namspace App\Http\Controllers;
class UserController extends Controller
{
public array $store = [];
public function index(Request $request)
{
$nameList = ['james', 'lucy', 'jack', 'jessica', 'lily'];
$name = $nameList[array_rand($nameList)];
if (rand(0, 7) >= 2) { // 0-1 读 2-7 写
$test = new User();
$test->name = $name;
$test->password = Hash::make(123456);
$test->role = 2;
$test->created_at = time();
$test->updated_at = time();
$test->deleted_at = time();
$test->save();
$data = ['id' => $test->id];
} else {
$data = User::query()->where('name', $name)->first();;
}
}
}
4. 添加路由
# web.php
Route::get('test-mysql', 'UserController@index');
5. 开始压测
压测命令
ab -n 1000 -c 8 http://127.0.0.1:8010/test-mysql
-n 1000
: 指定测试会话使用的请求数为1000-c 8
: 8个并发请求
使用 Octane
压测结果如下:
[root@localhost octane]# ab -n 1000 -c 8 http://127.0.0.1:8010/test-mysql
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 127.0.0.1 (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software:
Server Hostname: 127.0.0.1
Server Port: 8010
Document Path: /test-mysql
Document Length: 0 bytes
Concurrency Level: 8
Time taken for tests: 22.268 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 1048000 bytes
HTML transferred: 0 bytes
Requests per second: 44.91 [#/sec] (mean)
Time per request: 178.141 [ms] (mean)
Time per request: 22.268 [ms] (mean, across all concurrent requests)
Transfer rate: 45.96 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 1
Processing: 14 177 43.8 180 327
Waiting: 14 177 43.8 179 327
Total: 14 177 43.8 180 327
Percentage of the requests served within a certain time (ms)
50% 180
66% 195
75% 207
80% 217
90% 230
95% 241
98% 254
99% 261
100% 327 (longest request)
再看看不用 Octane
时的压测结果
执行一下命令,8008
是我单独配置的端口,不经过 octane
ab -n 1000 -c 8 http://127.0.0.1:8008/test-mysql
结果:
[root@localhost octane]# ab -n 1000 -c 8 http://127.0.0.1:8008/test-mysql
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 127.0.0.1 (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: nginx/1.20.1
Server Hostname: 127.0.0.1
Server Port: 8008
Document Path: /test-mysql
Document Length: 0 bytes
Concurrency Level: 8
Time taken for tests: 55.076 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 1134000 bytes
HTML transferred: 0 bytes
Requests per second: 18.16 [#/sec] (mean)
Time per request: 440.606 [ms] (mean)
Time per request: 55.076 [ms] (mean, across all concurrent requests)
Transfer rate: 20.11 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 70 438 193.7 424 1587
Waiting: 70 438 193.7 424 1587
Total: 70 438 193.7 424 1588
Percentage of the requests served within a certain time (ms)
50% 424
66% 511
75% 565
80% 593
90% 652
95% 705
98% 783
99% 1183
100% 1588 (longest request)
根据上面两种结果的比较可以看出,octane
速度明显提升了几倍。
Step6. 优势与劣势
1. 优势
在 Octane
之前,我们一直用 Nginx + PHP-FPM
的组合,它执行的顺序是:
- 一个请求来到
Nginx
。 Nginx
将请求委托给PHP-FPM
。PHP-FPM
要么产生一个新的woker
,要么使用一个现有的woker
来处理请求。PHP-FPM worker
启动 Laravel 应用程序。Laravel
的应用程序处理请求。PHP-FPM
将结果返回给Nginx
,Nginx
将输出返回给客户端。
如上所述,每个请求从开始创建进程和到启动 Laravel 应用程序都会产生开销。在第4步中,lavale 框架会加载所有需要的依赖,包括 vendor包
, Service Providers
, Middleware
和 route
等等,随着第三方 service
越来越多,启动速度越来越不受控。
Laravel Octane
则通过启动 Application 一次,常驻内存的方式来加速应用
2. 劣势
- 服务容器注入可能绑定不成功
- HTTP Request 注入时请求参数可能会不正确
- 可能会出现内存泄漏的情况
结语:
Laravel Octane
离新发布只有几个月的时间,对于很多开发者来说,它并不是必须的,因为许多应用瓶颈都与未优化的数据库查询、缓慢的会话存储或缓慢的外部 API
请求有关。如果要在自己的项目中使用 Laravel Octane
,就要做好会遇到更多让人头疼的问题的准备。
下一篇会讲解 RoadRunner
的使用。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。