LaravelS开发记录

主要记录了由普通PHP开发者初步接触laravelS是所遇到的一些小坑

➡️LaravelS介绍

1
2
3
4
5
6
 _                               _  _____
| | | |/ ____|
| | __ _ _ __ __ ___ _____| | (___
| | / _` | '__/ _` \ \ / / _ \ |\___ \
| |___| (_| | | | (_| |\ V / __/ |____) |
|______\__,_|_| \__,_| \_/ \___|_|_____/

LaravelS是一个能够使普通的laravel项目尽快的享受上swoole的优势的laravel插件
官方描述:
🚀LaravelS是一个胶水项目,用于快速集成Swoole到Laravel或Lumen,然后赋予它们更好的性能、更多可能性。

GitHub地址:

文档地址:
laravel-s/README-CN.md
Laravel-China地址:
LaravelS - 基于 Swoole 加速 Laravel/Lumen - 带你飞 🚀

➡️安装

➡️安装要求

依赖说明
PHP>= 5.5.9 推荐PHP7+
Swoole>= 1.7.19 从2.0.12开始不再支持PHP5 推荐4.2.3+
Laravel/Lumen>= 5.1 推荐5.6+

➡️安装swoole

详细请参考 swoole安装

➡️安装laravel

可以通过composer直接安装,或者安装安装器或者直接从GitHub拷贝源代码来安装

➡️安装laravelS

  1. 通过Composer安装
1
2
composer require "hhxsv5/laravel-s:~3.0" -vvv
# 确保你的composer.lock文件是在版本控制中
  1. 注册Service Provider
    • Laravel: 修改文件config/app.php,Laravel 5.5+支持包自动发现,你应该跳过这步
1
2
3
4
'providers' => [
//...
Hhxsv5\LaravelS\Illuminate\LaravelSServiceProvider::class,
],
- Lumen: 修改文件`bootstrap/app.php`
1
$app->register(Hhxsv5\LaravelS\Illuminate\LaravelSServiceProvider::class);
  1. 发布配置文件.
1
php artisan laravels publish

如果你用的是lumen,不需要加载config/laravels.php

1
2
//这个可有可无
$app->configure('laravels');
  1. 修改配置config/laravels.php
    请参考laravelS配置项

➡️运行

1
php artisan laravels {start|stop|restart|reload|publish}
命令说明
start启动LaravelS。选项-d--daemonize以守护进程的方式运行,此选项将覆盖laravels.phpswoole.daemonize设置
stop停止LaravelS
restart重启LaravelS,支持选项-d--daemonize
reload平滑重启所有worker进程,这些worker进程内包含你的业务代码和框架(Laravel/Lumen)代码,不会重启master/manger进程
publish发布配置文件到你的项目中config/laravels.php

ps:展示已经启动的项目:
ps -ef|grep laravels

➡️配置nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
gzip on;
gzip_min_length 1024;
gzip_comp_level 2;
gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml application/x-httpd-php image/jpeg image/gif image/png font/ttf font/otf image/svg+xml;
gzip_vary on;
gzip_disable "msie6";
upstream laravels {
# By IP:Port
server 127.0.0.1:9100 weight=5 max_fails=3 fail_timeout=30s; #这里配置的是laravelS监听的接口参数
# By UnixSocket Stream file
#server unix:/xxxpath/laravel-s-test/storage/laravels.sock weight=5 max_fails=3 fail_timeout=30s;
#server 192.168.1.1:5200 weight=3 max_fails=3 fail_timeout=30s;
#server 192.168.1.2:5200 backup;
}
server {
listen 80;
server_name laravels.com;
#为了给nginx定位静态资源
root /xxxpath/laravel-s-test/public;
# Nginx处理静态资源(建议开启gzip),LaravelS处理动态资源。
location / {
try_files $uri @laravels;
}

location @laravels {
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 120s;
proxy_set_header Connection "keep-alive";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-PORT $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header Scheme $scheme;
proxy_set_header Server-Protocol $server_protocol;
proxy_set_header Server-Name $server_name;
proxy_set_header Server-Addr $server_addr;
proxy_set_header Server-Port $server_port;
proxy_pass http://laravels;
}
}

➡️配置Apache

ps:我用的是nginx,没有实际配置过,就直接把官方文档里的拿过来了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
LoadModule proxy_module /yyypath/modules/mod_deflate.so
<IfModule deflate_module>
SetOutputFilter DEFLATE
DeflateCompressionLevel 2
AddOutputFilterByType DEFLATE text/html text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml application/x-httpd-php image/jpeg image/gif image/png font/ttf font/otf image/svg+xml
</IfModule>

<VirtualHost *:80>
# 别忘了绑Host哟
ServerName www.laravels.com
ServerAdmin [email protected]

DocumentRoot /xxxpath/laravel-s-test/public;
DirectoryIndex index.html index.htm
<Directory "/">
AllowOverride None
Require all granted
</Directory>

LoadModule proxy_module /yyypath/modules/mod_proxy.so
LoadModule proxy_module /yyypath/modules/mod_proxy_balancer.so
LoadModule proxy_module /yyypath/modules/mod_lbmethod_byrequests.so.so
LoadModule proxy_module /yyypath/modules/mod_proxy_http.so.so
LoadModule proxy_module /yyypath/modules/mod_slotmem_shm.so
LoadModule proxy_module /yyypath/modules/mod_rewrite.so

ProxyRequests Off
ProxyPreserveHost On
<Proxy balancer://laravels>
BalancerMember http://192.168.1.1:8011 loadfactor=7
#BalancerMember http://192.168.1.2:8011 loadfactor=3
#BalancerMember http://192.168.1.3:8011 loadfactor=1 status=+H
ProxySet lbmethod=byrequests
</Proxy>
#ProxyPass / balancer://laravels/
#ProxyPassReverse / balancer://laravels/

# Apache处理静态资源,LaravelS处理动态资源。
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://laravels/%{REQUEST_URI} [P,L]

ErrorLog ${APACHE_LOG_DIR}/www.laravels.com.error.log
CustomLog ${APACHE_LOG_DIR}/www.laravels.com.access.log combined
</VirtualHost>

➡️自定义的异步任务

此特性依赖SwooleAsyncTask,必须先设置config/laravels.phpswoole.task_worker_num
异步事件的处理能力受Task进程数影响,需合理设置task_worker_num
任务结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
namespace App\Task\Message;

use App\Traits\Push;
use Hhxsv5\LaravelS\Swoole\Task\Task;

class Reply extends Task
{
private $data;

public function __construct($data)
{
$this->data = $data;
}

/**
* 任务逻辑
*/
public function handle()
{
//Do something
}
}

ps: 任务里没有依赖注入这种便捷的东西
投递任务

1
2
3
4
5
6
// 实例化$action并通过deliver投递
//此操作是异步的,投递后立即返回
//由Task进程继续处理$action中的handle逻辑
$task = new \App\Task\Message\Reply($dat);
// $task->delay(3);// 延迟3秒投放任务
\Hhxsv5\LaravelS\Swoole\Task\Task::deliver($task);

➡️laravelS配置项

  • listen_ipstring 监听的IP,监听本机127.0.0.1(IPv4) ::1(IPv6),监听所有地址 0.0.0.0(IPv4) ::(IPv6), 默认127.0.0.1

  • listen_portint 监听的端口,如果端口小于1024则需要root权限,default 5200

  • socket_type:默认SWOOLE_SOCK_TCP。通常情况下,无需关心这个配置。若需Nginx代理至UnixSocket Stream文件,则需修改为SWOOLE_SOCK_UNIX_STREAM,此时listen_ip则是UnixSocket Stream文件的路径。

  • enable_gzip:bool 当通过LaravelS响应数据时,是否启用gzip压缩响应的内容,依赖库zlib,通过命令php --ri swoole|grep zlib检查gzip是否可用。如果开启则会自动加上头部Content-Encoding,默认false。如果存在代理服务器(例如Nginx),建议代理服务器开启gzipLaravelS关闭gzip,避免重复gzip压缩。

  • serverstring 当通过LaravelS响应数据时,设置HTTP头部Server的值,若为空则不设置,default LaravelS

  • handle_staticbool 是否开启LaravelS处理静态资源(要求 Swoole >= 1.7.21,若Swoole >= 1.9.17则由Swoole自己处理),默认false,建议Nginx处理静态资源,LaravelS仅处理动态资源。静态资源的默认路径为base_path('public'),可通过修改swoole.document_root变更。

  • laravel_base_pathstring Laravel/Lumen的基础路径,默认base_path(),可用于配置符号链接。

  • inotify_reload.enablebool 是否开启Inotify Reload,用于当修改代码后实时Reload所有worker进程,依赖库inotify,通过命令php --ri inotify检查是否可用,默认false,建议仅开发环境开启,修改监听数上限。

  • inotify_reload.watch_pathstring Inotify 监控的文件路径,默认有base_path()

  • inotify_reload.file_typesarray Inotify 监控的文件类型,默认有.php

  • inotify_reload.logbool 是否输出Reload的日志,默认true

  • websocket.enablebool 是否启用WebSocket服务器。启用后WebSocket服务器监听的IP和端口与Http服务器相同,默认false

  • websocket.handlerstring WebSocket逻辑处理的类名,需实现接口WebSocketHandlerInterface,参考示例。

  • socketsarray 配置TCP/UDP套接字列表,参考示例。

  • processesarray 配置自定义进程列表,参考示例。

  • eventsarray 自定义的异步事件和监听的绑定列表,参考示例。

  • swoole_tablesarray 定义的swoole_table列表,参考示例。

  • register_providersarray 每次请求需要重新注册的Service Provider列表,若存在boot()方法,会自动执行。一般用于清理注册了单例的ServiceProvider

1
2
3
4
5
6
//...
'register_providers' => [
//例如:重新注册jwt的ServiceProvider
\Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
],
//...