Dokumen Bahasa Inggris | 中文文档
LaravelS adalah adaptor out-of-the-box antara Laravel/Lumen dan Swoole
Watch
repositori ini untuk mendapatkan pembaruan terkini.Server Http/WebSocket bawaan
Protokol campuran multi-port
Proses khusus
Penduduk memori
Mendengarkan acara asinkron
Antrean tugas asinkron
Pekerjaan cron milidetik
Komponen Umum
Muat ulang dengan anggun
Muat ulang secara otomatis setelah mengubah kode
Mendukung Laravel/Lumen keduanya, kompatibilitas bagus
Sederhana & di luar kotak
Kerangka web mana yang tercepat?
Tolok Ukur Kerangka Kerja TechEmpower
Ketergantungan | Persyaratan |
---|---|
PHP | >=8.2 Recommend 8.2 |
berputar-putar | >=5.0 Recommend 5.1.1 |
Laravel/Lumen | >=10 Recommend 10 |
1.Memerlukan paket melalui Composer (packagist).
# PHP >=8.2
composer require " hhxsv5/laravel-s:~3.8.0 "
# PHP >=5.5.9,<=7.4.33
# composer require "hhxsv5/laravel-s:~3.7.0"
# Make sure that your composer.lock file is under the VCS
2.Daftarkan penyedia layanan (pilih salah satu dari dua).
Laravel
: di file config/app.php
, Laravel 5.5+ supports package discovery automatically, you should skip this step
' providers ' => [
//...
Hhxsv5 LaravelS Illuminate LaravelSServiceProvider::class,
],
Lumen
: dalam file bootstrap/app.php
$ app -> register ( Hhxsv5 LaravelS Illuminate LaravelSServiceProvider::class);
3.Publikasikan konfigurasi dan binari.
Setelah memutakhirkan LaravelS, Anda perlu menerbitkan ulang; klik di sini untuk melihat catatan perubahan setiap versi.
php artisan laravels publish
# Configuration: config/laravels.php
# Binary: bin/laravels bin/fswatch bin/inotify
4.Ubah config/laravels.php
: mendengarkan_ip, mendengarkan_port, lihat Pengaturan.
5. Penyetelan kinerja
Sesuaikan parameter kernel
Jumlah Pekerja: LaravelS menggunakan mode Synchronous IO
Swoole, semakin besar pengaturan worker_num
, semakin baik kinerja konkurensi, tetapi akan menyebabkan lebih banyak penggunaan memori dan overhead peralihan proses. Jika satu permintaan memerlukan waktu 100 md, untuk menyediakan konkurensi 1000QPS, setidaknya 100 proses Pekerja perlu dikonfigurasi. Metode penghitungannya adalah:worker_num = 1000QPS/(1s/1ms) = 100, sehingga pengujian tekanan tambahan diperlukan untuk worker_num
terbaik.
Jumlah Pekerja Tugas
Please read the notices carefully before running
, Pemberitahuan penting (PENTING).
php bin/laravels {start|stop|restart|reload|info|help}
.Memerintah | Keterangan |
---|---|
awal | Mulai LaravelS, daftarkan prosesnya dengan " ps -ef|grep laravels " |
berhenti | Hentikan LaravelS, dan picu metode onStop pada proses Custom |
memulai ulang | Mulai ulang LaravelS: Berhenti dengan baik sebelum memulai; Layanan ini unavailable hingga pengaktifan selesai |
memuat ulang | Muat ulang semua proses Tugas/Pekerja/Pengatur Waktu yang berisi kode bisnis Anda, dan picu metode onReload dari proses Kustom, TIDAK BISA memuat ulang proses Master/Manger. Setelah memodifikasi config/laravels.php , Anda only perlu memanggil restart untuk memulai ulang |
info | Menampilkan informasi versi komponen |
membantu | Menampilkan informasi bantuan |
start
dan restart
.Pilihan | Keterangan |
---|---|
-d|--melakukan daemonisasi | Jalankan sebagai daemon, opsi ini akan mengesampingkan pengaturan swoole.daemonize di laravels.php |
-e|--env | Lingkungan tempat perintah harus dijalankan, seperti --env=testing akan menggunakan file konfigurasi .env.testing terlebih dahulu, fitur ini memerlukan Laravel 5.2+ |
-i|--abaikan | Abaikan pemeriksaan file PID dari proses Master |
-x|--x-versi | Versi(cabang) proyek saat ini, disimpan di $_ENV/$_SERVER, akses melalui $_ENV['X_VERSION'] $_SERVER['X_VERSION'] $request->server->get('X_VERSION') |
Runtime
: start
akan secara otomatis mengeksekusi php artisan laravels config
dan menghasilkan file-file ini, pengembang umumnya tidak perlu memperhatikannya, disarankan untuk menambahkannya ke .gitignore
.Mengajukan | Keterangan |
---|---|
penyimpanan/laravels.conf | File konfigurasi runtime LaravelS |
penyimpanan/laravels.pid | File PID dari proses Master |
penyimpanan/laravels-timer-process.pid | File PID dari proses Timer |
penyimpanan/laravels-custom-processes.pid | File PID dari semua proses khusus |
Disarankan untuk mengawasi proses utama melalui Supervisord, premisnya tanpa opsi
-d
dan menyetelswoole.daemonize
kefalse
.
[program:laravel-s-test]
directory=/var/www/laravel-s-test
command=/usr/local/bin/php bin/laravels start -i
numprocs=1
autostart=true
autorestart=true
startretries=3
user=www-data
redirect_stderr=true
stdout_logfile=/var/log/supervisor/%(program_name)s.log
Demo.
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 swoole {
# Connect IP:Port
server 127.0.0.1:5200 weight=5 max_fails=3 fail_timeout=30s;
# Connect UnixSocket Stream file, tips: put the socket file in the /dev/shm directory to get better performance
#server unix:/yourpath/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;
keepalive 16;
}
server {
listen 80 ;
# Don't forget to bind the host
server_name laravels.com;
root /yourpath/laravel-s-test/public;
access_log /yourpath/log/nginx/ $server_name .access.log main ;
autoindex off ;
index index.html index.htm;
# Nginx handles the static resources(recommend enabling gzip), LaravelS handles the dynamic resource.
location / {
try_files $uri @laravels;
}
# Response 404 directly when request the PHP file, to avoid exposing public/*.php
#location ~* .php$ {
# return 404;
#}
location @laravels {
# proxy_connect_timeout 60s;
# proxy_send_timeout 60s;
# proxy_read_timeout 120s;
proxy_http_version 1.1 ;
proxy_set_header Connection "" ;
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 ;
# "swoole" is the upstream
proxy_pass http://swoole;
}
}
LoadModule proxy_module /yourpath/modules/mod_proxy.so
LoadModule proxy_balancer_module /yourpath/modules/mod_proxy_balancer.so
LoadModule lbmethod_byrequests_module /yourpath/modules/mod_lbmethod_byrequests.so
LoadModule proxy_http_module /yourpath/modules/mod_proxy_http.so
LoadModule slotmem_shm_module /yourpath/modules/mod_slotmem_shm.so
LoadModule rewrite_module /yourpath/modules/mod_rewrite.so
LoadModule remoteip_module /yourpath/modules/mod_remoteip.so
LoadModule deflate_module /yourpath/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>
# Don't forget to bind the host
ServerName www.laravels.com
ServerAdmin [email protected]
DocumentRoot /yourpath/laravel-s-test/public;
DirectoryIndex index.html index.htm
< Directory "/">
AllowOverride None
Require all granted
</ Directory >
RemoteIPHeader X-Forwarded-For
ProxyRequests Off
ProxyPreserveHost On
< Proxy balancer://laravels>
BalancerMember http://192.168.1.1:5200 loadfactor=7
# BalancerMember http://192.168.1.2:5200 loadfactor=3
# BalancerMember http://192.168.1.3:5200 loadfactor=1 status=+H
ProxySet lbmethod=byrequests
</ Proxy >
# ProxyPass / balancer://laravels/
# ProxyPassReverse / balancer://laravels/
# Apache handles the static resources, LaravelS handles the dynamic resource.
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 >
Alamat Mendengarkan WebSocket Sever sama dengan Http Server.
1.Buat kelas WebSocket Handler, dan implementasikan antarmuka WebSocketHandlerInterface
. Instan secara otomatis dibuat saat mulai, Anda tidak perlu membuatnya secara manual.
namespace App Services ;
use Hhxsv5 LaravelS Swoole WebSocketHandlerInterface ;
use Swoole Http Request ;
use Swoole Http Response ;
use Swoole WebSocket Frame ;
use Swoole WebSocket Server ;
/**
* @see https://www.swoole.co.uk/docs/modules/swoole-websocket-server
*/
class WebSocketService implements WebSocketHandlerInterface
{
// Declare constructor without parameters
public function __construct ()
{
}
// public function onHandShake(Request $request, Response $response)
// {
// Custom handshake: https://www.swoole.co.uk/docs/modules/swoole-websocket-server-on-handshake
// The onOpen event will be triggered automatically after a successful handshake
// }
public function onOpen ( Server $ server , Request $ request )
{
// Before the onOpen event is triggered, the HTTP request to establish the WebSocket has passed the Laravel route,
// so Laravel's Request, Auth information are readable, Session is readable and writable, but only in the onOpen event.
// Log::info('New WebSocket connection', [$request->fd, request()->all(), session()->getId(), session('xxx'), session(['yyy' => time()])]);
// The exceptions thrown here will be caught by the upper layer and recorded in the Swoole log. Developers need to try/catch manually.
$ server -> push ( $ request -> fd , ' Welcome to LaravelS ' );
}
public function onMessage ( Server $ server , Frame $ frame )
{
// Log::info('Received message', [$frame->fd, $frame->data, $frame->opcode, $frame->finish]);
// The exceptions thrown here will be caught by the upper layer and recorded in the Swoole log. Developers need to try/catch manually.
$ server -> push ( $ frame -> fd , date ( ' Y-m-d H:i:s ' ));
}
public function onClose ( Server $ server , $ fd , $ reactorId )
{
// The exceptions thrown here will be caught by the upper layer and recorded in the Swoole log. Developers need to try/catch manually.
}
}
2.Modifikasi config/laravels.php
.
// ...
' websocket ' => [
' enable ' => true , // Note: set enable to true
' handler ' => App Services WebSocketService::class,
],
' swoole ' => [
//...
// Must set dispatch_mode in (2, 4, 5), see https://www.swoole.co.uk/docs/modules/swoole-server/configuration
' dispatch_mode ' => 2 ,
//...
],
// ...
3.Gunakan SwooleTable
untuk mengikat FD & UserId, opsional, Demo Tabel Swoole. Anda juga dapat menggunakan layanan penyimpanan global lainnya, seperti Redis/Memcached/MySQL, namun hati-hati karena FD mungkin mengalami konflik antara beberapa Swoole Servers
.
4.Bekerjasama dengan Nginx (Disarankan)
Lihat Proksi WebSocket
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream swoole {
# Connect IP:Port
server 127.0.0.1:5200 weight=5 max_fails=3 fail_timeout=30s;
# Connect UnixSocket Stream file, tips: put the socket file in the /dev/shm directory to get better performance
#server unix:/yourpath/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;
keepalive 16;
}
server {
listen 80 ;
# Don't forget to bind the host
server_name laravels.com;
root /yourpath/laravel-s-test/public;
access_log /yourpath/log/nginx/ $server_name .access.log main ;
autoindex off ;
index index.html index.htm;
# Nginx handles the static resources(recommend enabling gzip), LaravelS handles the dynamic resource.
location / {
try_files $uri @laravels;
}
# Response 404 directly when request the PHP file, to avoid exposing public/*.php
#location ~* .php$ {
# return 404;
#}
# Http and WebSocket are concomitant, Nginx identifies them by "location"
# !!! The location of WebSocket is "/ws"
# Javascript: var ws = new WebSocket("ws://laravels.com/ws");
location =/ws {
# proxy_connect_timeout 60s;
# proxy_send_timeout 60s;
# proxy_read_timeout: Nginx will close the connection if the proxied server does not send data to Nginx in 60 seconds; At the same time, this close behavior is also affected by heartbeat setting of Swoole.
# proxy_read_timeout 60s;
proxy_http_version 1.1 ;
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_set_header Upgrade $http_upgrade ;
proxy_set_header Connection $connection_upgrade ;
proxy_pass http://swoole;
}
location @laravels {
# proxy_connect_timeout 60s;
# proxy_send_timeout 60s;
# proxy_read_timeout 60s;
proxy_http_version 1.1 ;
proxy_set_header Connection "" ;
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://swoole;
}
}
5. Pengaturan detak jantung
Pengaturan detak jantung Swoole
// config/laravels.php
' swoole ' => [
//...
// All connections are traversed every 60 seconds. If a connection does not send any data to the server within 600 seconds, the connection will be forced to close.
' heartbeat_idle_time ' => 600 ,
' heartbeat_check_interval ' => 60 ,
//...
],
Batas waktu pembacaan proxy Nginx
# Nginx will close the connection if the proxied server does not send data to Nginx in 60 seconds
proxy_read_timeout 60s ;
6. Dorong data ke pengontrol
namespace App Http Controllers ;
class TestController extends Controller
{
public function push ()
{
$ fd = 1 ; // Find fd by userId from a map [userId=>fd].
/**@var SwooleWebSocketServer $swoole */
$ swoole = app ( ' swoole ' );
$ success = $ swoole -> push ( $ fd , ' Push data to fd#1 in Controller ' );
var_dump ( $ success );
}
}
Biasanya, Anda dapat mengatur ulang/menghancurkan beberapa variabel
global/static
, atau mengubah objekRequest/Response
saat ini.
laravels.received_request
Setelah LaravelS menguraikan SwooleHttpRequest
ke IlluminateHttpRequest
, sebelum Kernel Laravel menangani permintaan ini.
// Edit file `app/Providers/EventServiceProvider.php`, add the following code into method `boot`
// If no variable $events, you can also call Facade Event::listen().
$ events -> listen ( ' laravels.received_request ' , function ( Illuminate Http Request $ req , $ app ) {
$ req -> query -> set ( ' get_key ' , ' hhxsv5 ' ); // Change query of request
$ req -> request -> set ( ' post_key ' , ' hhxsv5 ' ); // Change post of request
});
laravels.generated_response
Setelah Kernel Laravel menangani permintaan, sebelum LaravelS mem-parsing IlluminateHttpResponse
ke SwooleHttpResponse
.
// Edit file `app/Providers/EventServiceProvider.php`, add the following code into method `boot`
// If no variable $events, you can also call Facade Event::listen().
$ events -> listen ( ' laravels.generated_response ' , function ( Illuminate Http Request $ req , Symfony Component HttpFoundation Response $ rsp , $ app ) {
$ rsp -> headers -> set ( ' header-key ' , ' hhxsv5 ' ); // Change header of response
});
Fitur ini bergantung pada
AsyncTask
dariSwoole
, Anda perlu menyetelswoole.task_worker_num
diconfig/laravels.php
terlebih dahulu. Kinerja pemrosesan kejadian asinkron dipengaruhi oleh jumlah proses tugas Swoole, Anda perlu mengatur task_worker_num dengan tepat.
1.Buat kelas acara.
use Hhxsv5 LaravelS Swoole Task Event ;
class TestEvent extends Event
{
protected $ listeners = [
// Listener list
TestListener1::class,
// TestListener2::class,
];
private $ data ;
public function __construct ( $ data )
{
$ this -> data = $ data ;
}
public function getData ()
{
return $ this -> data ;
}
}
2.Buat kelas pendengar.
use Hhxsv5 LaravelS Swoole Task Event ;
use Hhxsv5 LaravelS Swoole Task Task ;
use Hhxsv5 LaravelS Swoole Task Listener ;
class TestListener1 extends Listener
{
public function handle ( Event $ event )
{
Log:: info ( __CLASS__ . ' :handle start ' , [ $ event -> getData ()]);
sleep ( 2 ); // Simulate the slow codes
// Deliver task in CronJob, but NOT support callback finish() of task.
// Note: Modify task_ipc_mode to 1 or 2 in config/laravels.php, see https://www.swoole.co.uk/docs/modules/swoole-server/configuration
$ ret = Task:: deliver ( new TestTask ( ' task data ' ));
var_dump ( $ ret );
// The exceptions thrown here will be caught by the upper layer and recorded in the Swoole log. Developers need to try/catch manually.
// return false; // Stop propagating this event to subsequent listeners
}
}
3. Peristiwa kebakaran.
// Create instance of event and fire it, "fire" is asynchronous.
use Hhxsv5 LaravelS Swoole Task Event ;
$ event = new TestEvent ( ' event data ' );
// $event->delay(10); // Delay 10 seconds to fire event
// $event->setTries(3); // When an error occurs, try 3 times in total
$ success = Event:: fire ( $ event );
var_dump ( $ success ); // Return true if sucess, otherwise false
Fitur ini bergantung pada
AsyncTask
dariSwoole
, Anda perlu menyetelswoole.task_worker_num
diconfig/laravels.php
terlebih dahulu. Kinerja pemrosesan tugas dipengaruhi oleh jumlah proses tugas Swoole, Anda perlu mengatur task_worker_num dengan tepat.
1.Buat kelas tugas.
use Hhxsv5 LaravelS Swoole Task Task ;
class TestTask extends Task
{
private $ data ;
private $ result ;
public function __construct ( $ data )
{
$ this -> data = $ data ;
}
// The logic of task handling, run in task process, CAN NOT deliver task
public function handle ()
{
Log:: info ( __CLASS__ . ' :handle start ' , [ $ this -> data ]);
sleep ( 2 ); // Simulate the slow codes
// The exceptions thrown here will be caught by the upper layer and recorded in the Swoole log. Developers need to try/catch manually.
$ this -> result = ' the result of ' . $ this -> data ;
}
// Optional, finish event, the logic of after task handling, run in worker process, CAN deliver task
public function finish ()
{
Log:: info ( __CLASS__ . ' :finish start ' , [ $ this -> result ]);
Task:: deliver ( new TestTask2 ( ' task2 data ' )); // Deliver the other task
}
}
2. Menyerahkan tugas.
// Create instance of TestTask and deliver it, "deliver" is asynchronous.
use Hhxsv5 LaravelS Swoole Task Task ;
$ task = new TestTask ( ' task data ' );
// $task->delay(3);// delay 3 seconds to deliver task
// $task->setTries(3); // When an error occurs, try 3 times in total
$ ret = Task:: deliver ( $ task );
var_dump ( $ ret ); // Return true if sucess, otherwise false
Pekerjaan wrapper cron berdasarkan Timer Milidetik Swoole, ganti
Linux
Crontab
.
1.Buat kelas pekerjaan cron.
namespace App Jobs Timer ;
use App Tasks TestTask ;
use Swoole Coroutine ;
use Hhxsv5 LaravelS Swoole Task Task ;
use Hhxsv5 LaravelS Swoole Timer CronJob ;
class TestCronJob extends CronJob
{
protected $ i = 0 ;
// !!! The `interval` and `isImmediate` of cron job can be configured in two ways(pick one of two): one is to overload the corresponding method, and the other is to pass parameters when registering cron job.
// --- Override the corresponding method to return the configuration: begin
public function interval ()
{
return 1000 ; // Run every 1000ms
}
public function isImmediate ()
{
return false ; // Whether to trigger `run` immediately after setting up
}
// --- Override the corresponding method to return the configuration: end
public function run ()
{
Log:: info ( __METHOD__ , [ ' start ' , $ this -> i , microtime ( true )]);
// do something
// sleep(1); // Swoole < 2.1
Coroutine:: sleep ( 1 ); // Swoole>=2.1 Coroutine will be automatically created for run().
$ this -> i ++;
Log:: info ( __METHOD__ , [ ' end ' , $ this -> i , microtime ( true )]);
if ( $ this -> i >= 10 ) { // Run 10 times only
Log:: info ( __METHOD__ , [ ' stop ' , $ this -> i , microtime ( true )]);
$ this -> stop (); // Stop this cron job, but it will run again after restart/reload.
// Deliver task in CronJob, but NOT support callback finish() of task.
// Note: Modify task_ipc_mode to 1 or 2 in config/laravels.php, see https://www.swoole.co.uk/docs/modules/swoole-server/configuration
$ ret = Task:: deliver ( new TestTask ( ' task data ' ));
var_dump ( $ ret );
}
// The exceptions thrown here will be caught by the upper layer and recorded in the Swoole log. Developers need to try/catch manually.
}
}
2.Daftarkan pekerjaan cron.
// Register cron jobs in file "config/laravels.php"
[
// ...
' timer ' => [
' enable ' => true , // Enable Timer
' jobs ' => [ // The list of cron job
// Enable LaravelScheduleJob to run `php artisan schedule:run` every 1 minute, replace Linux Crontab
// Hhxsv5LaravelSIlluminateLaravelScheduleJob::class,
// Two ways to configure parameters:
// [AppJobsTimerTestCronJob::class, [1000, true]], // Pass in parameters when registering
App Jobs Timer TestCronJob::class, // Override the corresponding method to return the configuration
],
' max_wait_time ' => 5 , // Max waiting time of reloading
// Enable the global lock to ensure that only one instance starts the timer when deploying multiple instances. This feature depends on Redis, please see https://laravel.com/docs/7.x/redis
' global_lock ' => false ,
' global_lock_key ' => config ( ' app.name ' , ' Laravel ' ),
],
// ...
];
3.Catatan: ini akan meluncurkan beberapa pengatur waktu saat membangun cluster server, jadi Anda perlu memastikan bahwa meluncurkan satu pengatur waktu saja untuk menghindari menjalankan tugas yang berulang.
4.LaravelS v3.4.0
mulai mendukung proses Timer
hot restart [Reload]. Setelah LaravelS menerima sinyal SIGUSR1
, menunggu max_wait_time
(default 5) detik untuk mengakhiri proses, kemudian proses Manager
akan menarik kembali proses Timer
.
5.Jika Anda hanya perlu menggunakan tugas terjadwal minute-level
, disarankan untuk mengaktifkan Hhxsv5LaravelSIlluminateLaravelScheduleJob
daripada Linux Crontab, sehingga Anda dapat mengikuti kebiasaan pengkodean penjadwalan tugas Laravel dan mengonfigurasi Kernel
.
// app/Console/Kernel.php
protected function schedule ( Schedule $ schedule )
{
// runInBackground() will start a new child process to execute the task. This is asynchronous and will not affect the execution timing of other tasks.
$ schedule -> command (TestCommand::class)-> runInBackground ()-> everyMinute ();
}
Melalui inotify
, hanya mendukung Linux.
1.Instal ekstensi inotify.
2.Hidupkan sakelar di Pengaturan.
3.Pemberitahuan: Ubah file hanya di Linux
untuk menerima peristiwa perubahan file. Disarankan untuk menggunakan Docker terbaru. Solusi Gelandangan.
Melalui fswatch
, mendukung OS X/Linux/Windows.
1.Instal fswatch.
2.Jalankan perintah di direktori root proyek Anda.
# Watch current directory
./bin/fswatch
# Watch app directory
./bin/fswatch ./app
Melalui inotifywait
, dukung Linux.
1.Instal alat inotify.
2.Jalankan perintah di direktori root proyek Anda.
# Watch current directory
./bin/inotify
# Watch app directory
./bin/inotify ./app
Ketika metode di atas tidak berhasil, solusi utamanya: setel max_request=1,worker_num=1
, sehingga proses Worker
akan dimulai ulang setelah memproses permintaan. Kinerja metode ini sangat buruk, so only development environment use
.
SwooleServer
di proyek Anda /**
* $swoole is the instance of `SwooleWebSocketServer` if enable WebSocket server, otherwise `SwooleHttpServer`
* @var SwooleWebSocketServer|SwooleHttpServer $swoole
*/
$ swoole = app ( ' swoole ' );
var_dump ( $ swoole -> stats ());
$ swoole -> push ( $ fd , ' Push WebSocket message ' );
SwooleTable
1.Tentukan Tabel, dukung banyak.
Semua tabel yang ditentukan akan dibuat sebelum Swoole dimulai.
// in file "config/laravels.php"
[
// ...
' swoole_tables ' => [
// Scene:bind UserId & FD in WebSocket
' ws ' => [ // The Key is table name, will add suffix "Table" to avoid naming conflicts. Here defined a table named "wsTable"
' size ' => 102400 , // The max size
' column ' => [ // Define the columns
[ ' name ' => ' value ' , ' type ' => Swoole Table:: TYPE_INT , ' size ' => 8 ],
],
],
//...Define the other tables
],
// ...
];
2.Access Table
: semua instance tabel akan terikat pada SwooleServer
, diakses melalui app('swoole')->xxxTable
.
namespace App Services ;
use Hhxsv5 LaravelS Swoole WebSocketHandlerInterface ;
use Swoole Http Request ;
use Swoole WebSocket Frame ;
use Swoole WebSocket Server ;
class WebSocketService implements WebSocketHandlerInterface
{
/**@var SwooleTable $wsTable */
private $ wsTable ;
public function __construct ()
{
$ this -> wsTable = app ( ' swoole ' )-> wsTable ;
}
// Scene:bind UserId & FD in WebSocket
public function onOpen ( Server $ server , Request $ request )
{
// var_dump(app('swoole') === $server);// The same instance
/**
* Get the currently logged in user
* This feature requires that the path to establish a WebSocket connection go through middleware such as Authenticate.
* E.g:
* Browser side: var ws = new WebSocket("ws://127.0.0.1:5200/ws");
* Then the /ws route in Laravel needs to add the middleware like Authenticate.
* Route::get('/ws', function () {
* // Respond any content with status code 200
* return 'websocket';
* })->middleware(['auth']);
*/
// $user = Auth::user();
// $userId = $user ? $user->id : 0; // 0 means a guest user who is not logged in
$ userId = mt_rand ( 1000 , 10000 );
// if (!$userId) {
// // Disconnect the connections of unlogged users
// $server->disconnect($request->fd);
// return;
// }
$ this -> wsTable -> set ( ' uid: ' . $ userId , [ ' value ' => $ request -> fd ]); // Bind map uid to fd
$ this -> wsTable -> set ( ' fd: ' . $ request -> fd , [ ' value ' => $ userId ]); // Bind map fd to uid
$ server -> push ( $ request -> fd , " Welcome to LaravelS # { $ request -> fd }" );
}
public function onMessage ( Server $ server , Frame $ frame )
{
// Broadcast
foreach ( $ this -> wsTable as $ key => $ row ) {
if ( strpos ( $ key , ' uid: ' ) === 0 && $ server -> isEstablished ( $ row [ ' value ' ])) {
$ content = sprintf ( ' Broadcast: new message "%s" from #%d ' , $ frame -> data , $ frame -> fd );
$ server -> push ( $ row [ ' value ' ], $ content );
}
}
}
public function onClose ( Server $ server , $ fd , $ reactorId )
{
$ uid = $ this -> wsTable -> get ( ' fd: ' . $ fd );
if ( $ uid !== false ) {
$ this -> wsTable -> del ( ' uid: ' . $ uid [ ' value ' ]); // Unbind uid map
}
$ this -> wsTable -> del ( ' fd: ' . $ fd ); // Unbind fd map
$ server -> push ( $ fd , " Goodbye # { $ fd }" );
}
}
Untuk informasi lebih lanjut, silakan merujuk ke Swoole Server AddListener
Untuk membuat server utama kami mendukung lebih banyak protokol tidak hanya Http dan WebSocket, kami menghadirkan fitur multi-port mixed protocol
Swoole di LaravelS dan beri nama Socket
. Sekarang, Anda dapat membangun aplikasi TCP/UDP
dengan mudah di atas Laravel.
Buat kelas Socket
handler, dan perluas Hhxsv5LaravelSSwooleSocket{TcpSocket|UdpSocket|Http|WebSocket}
.
namespace App Sockets ;
use Hhxsv5 LaravelS Swoole Socket TcpSocket ;
use Swoole Server ;
class TestTcpSocket extends TcpSocket
{
public function onConnect ( Server $ server , $ fd , $ reactorId )
{
Log:: info ( ' New TCP connection ' , [ $ fd ]);
$ server -> send ( $ fd , ' Welcome to LaravelS. ' );
}
public function onReceive ( Server $ server , $ fd , $ reactorId , $ data )
{
Log:: info ( ' Received data ' , [ $ fd , $ data ]);
$ server -> send ( $ fd , ' LaravelS: ' . $ data );
if ( $ data === " quit rn" ) {
$ server -> send ( $ fd , ' LaravelS: bye ' . PHP_EOL );
$ server -> close ( $ fd );
}
}
public function onClose ( Server $ server , $ fd , $ reactorId )
{
Log:: info ( ' Close TCP connection ' , [ $ fd ]);
$ server -> send ( $ fd , ' Goodbye ' );
}
}
Koneksi Socket
ini berbagi proses pekerja yang sama dengan koneksi HTTP
/ WebSocket
Anda. Jadi tidak menjadi masalah sama sekali jika ingin menyampaikan tugas, menggunakan SwooleTable
, bahkan komponen Laravel seperti DB, Eloquent dan lain sebagainya. Pada saat yang sama, Anda dapat mengakses objek SwooleServerPort
secara langsung dengan properti anggota swoolePort
.
public function onReceive ( Server $ server , $ fd , $ reactorId , $ data )
{
$ port = $ this -> swoolePort ; // Get the `SwooleServerPort` object
}
namespace App Http Controllers ;
class TestController extends Controller
{
public function test ()
{
/**@var SwooleHttpServer|SwooleWebSocketServer $swoole */
$ swoole = app ( ' swoole ' );
// $swoole->ports: Traverse all Port objects, https://www.swoole.co.uk/docs/modules/swoole-server/multiple-ports
$ port = $ swoole -> ports [ 0 ]; // Get the `SwooleServerPort` object, $port[0] is the port of the main server
foreach ( $ port -> connections as $ fd ) { // Traverse all connections
// $swoole->send($fd, 'Send tcp message');
// if($swoole->isEstablished($fd)) {
// $swoole->push($fd, 'Send websocket message');
// }
}
}
}
Daftarkan Soket.
// Edit `config/laravels.php`
//...
' sockets ' => [
[
' host ' => ' 127.0.0.1 ' ,
' port ' => 5291 ,
' type ' => SWOOLE_SOCK_TCP , // Socket type: SWOOLE_SOCK_TCP/SWOOLE_SOCK_TCP6/SWOOLE_SOCK_UDP/SWOOLE_SOCK_UDP6/SWOOLE_UNIX_DGRAM/SWOOLE_UNIX_STREAM
' settings ' => [ // Swoole settings:https://www.swoole.co.uk/docs/modules/swoole-server-methods#swoole_server-addlistener
' open_eof_check ' => true ,
' package_eof ' => "rn" ,
],
' handler ' => App Sockets TestTcpSocket::class,
' enable ' => true , // whether to enable, default true
],
],
Mengenai konfigurasi detak jantung, hanya dapat diatur di main server
dan tidak dapat dikonfigurasi di Socket
, tetapi Socket
mewarisi konfigurasi detak jantung dari main server
.
Untuk soket TCP, acara onConnect
dan onClose
akan diblokir ketika dispatch_mode
dari Swoole adalah 1/3
, jadi jika Anda ingin membuka blokir kedua acara ini silakan atur dispatch_mode
ke 2/4/5
.
' swoole ' => [
//...
' dispatch_mode ' => 2 ,
//...
];
Tes.
TCP: telnet 127.0.0.1 5291
UDP: [Linux] echo "Hello LaravelS" > /dev/udp/127.0.0.1/5292
Daftarkan contoh protokol lain.
' sockets ' => [
[
' host ' => ' 0.0.0.0 ' ,
' port ' => 5292 ,
' type ' => SWOOLE_SOCK_UDP ,
' settings ' => [
' open_eof_check ' => true ,
' package_eof ' => "rn" ,
],
' handler ' => App Sockets TestUdpSocket::class,
],
],
' sockets ' => [
[
' host ' => ' 0.0.0.0 ' ,
' port ' => 5293 ,
' type ' => SWOOLE_SOCK_TCP ,
' settings ' => [
' open_http_protocol ' => true ,
],
' handler ' => App Sockets TestHttp::class,
],
],
turn on WebSocket
, yaitu menyetel websocket.enable
ke true
. ' sockets ' => [
[
' host ' => ' 0.0.0.0 ' ,
' port ' => 5294 ,
' type ' => SWOOLE_SOCK_TCP ,
' settings ' => [
' open_http_protocol ' => true ,
' open_websocket_protocol ' => true ,
],
' handler ' => App Sockets TestWebSocket::class,
],
],
Swoole Coroutine
Peringatan: Urutan eksekusi kode di coroutine tidak berurutan. Data tingkat permintaan harus diisolasi oleh ID coroutine. Namun, ada banyak atribut tunggal dan statis di Laravel/Lumen, data antar permintaan yang berbeda akan saling mempengaruhi, itu Unsafe
. Misalnya, koneksi database adalah singleton, koneksi database yang sama berbagi sumber daya PDO yang sama. Ini baik-baik saja dalam mode pemblokiran sinkron, tetapi tidak berfungsi dalam mode coroutine asinkron. Setiap kueri perlu membuat koneksi berbeda dan mempertahankan status IO dari koneksi berbeda, yang memerlukan kumpulan koneksi.
DO NOT
aktifkan coroutine, hanya proses kustom yang dapat menggunakan coroutine.
Mendukung pengembang untuk membuat proses kerja khusus untuk pemantauan, pelaporan, atau tugas khusus lainnya. Lihat addProcess.
Buat kelas Proses, implementasikan CustomProcessInterface.
namespace App Processes ;
use App Tasks TestTask ;
use Hhxsv5 LaravelS Swoole Process CustomProcessInterface ;
use Hhxsv5 LaravelS Swoole Task Task ;
use Swoole Coroutine ;
use Swoole Http Server ;
use Swoole Process ;
class TestProcess implements CustomProcessInterface
{
/**
* @var bool Quit tag for Reload updates
*/
private static $ quit = false ;
public static function callback ( Server $ swoole , Process $ process )
{
// The callback method cannot exit. Once exited, Manager process will automatically create the process
while (! self :: $ quit ) {
Log:: info ( ' Test process: running ' );
// sleep(1); // Swoole < 2.1
Coroutine:: sleep ( 1 ); // Swoole>=2.1: Coroutine & Runtime will be automatically enabled for callback(). Pay attention to the compatibility between the components used and the coroutines. If they are not compatible, only some coroutines can be enabled, such as: SwooleRuntime::enableCoroutine(SWOOLE_HOOK_TCP | SWOOLE_HOOK_SLEEP | SWOOLE_HOOK_FILE);
// Deliver task in custom process, but NOT support callback finish() of task.
// Note: Modify task_ipc_mode to 1 or 2 in config/laravels.php, see https://www.swoole.co.uk/docs/modules/swoole-server/configuration
$ ret = Task:: deliver ( new TestTask ( ' task data ' ));
var_dump ( $ ret );
// The upper layer will catch the exception thrown in the callback and record it in the Swoole log, and then this process will exit. The Manager process will re-create the process after 3 seconds, so developers need to try/catch to catch the exception by themselves to avoid frequent process creation.
// throw new Exception('an exception');
}
}
// Requirements: LaravelS >= v3.4.0 & callback() must be async non-blocking program.
public static function onReload ( Server $ swoole , Process $ process )
{
// Stop the process...
// Then end process
Log:: info ( ' Test process: reloading ' );
self :: $ quit = true ;
// $process->exit(0); // Force exit process
}
// Requirements: LaravelS >= v3.7.4 & callback() must be async non-blocking program.
public static function onStop ( Server $ swoole , Process $ process )
{
// Stop the process...
// Then end process
Log:: info ( ' Test process: stopping ' );
self :: $ quit = true ;
// $process->exit(0); // Force exit process
}
}
Daftarkan Proses Tes.
// Edit `config/laravels.php`
// ...
' processes ' => [
' test ' => [ // Key name is process name
' class ' => App Processes TestProcess::class,
' redirect ' => false , // Whether redirect stdin/stdout, true or false
' pipe ' => 0 , // The type of pipeline, 0: no pipeline 1: SOCK_STREAM 2: SOCK_DGRAM
' enable ' => true , // Whether to enable, default true
//'num' => 3 // To create multiple processes of this class, default is 1
//'queue' => [ // Enable message queue as inter-process communication, configure empty array means use default parameters
// 'msg_key' => 0, // The key of the message queue. Default: ftok(__FILE__, 1).
// 'mode' => 2, // Communication mode, default is 2, which means contention mode
// 'capacity' => 8192, // The length of a single message, is limited by the operating system kernel parameters. The default is 8192, and the maximum is 65536
//],
//'restart_interval' => 5, // After the process exits abnormally, how many seconds to wait before restarting the process, default 5 seconds
],
],
Catatan: Callback() tidak dapat ditutup. Jika berhenti, proses Manajer akan membuat ulang proses tersebut.
Contoh: Menulis data ke proses kustom.
// config/laravels.php
' processes ' => [
' test ' => [
' class ' => App Processes TestProcess::class,
' redirect ' => false ,
' pipe ' => 1 ,
],
],
// app/Processes/TestProcess.php
public static function callback ( Server $ swoole , Process $ process )
{
while ( $ data = $ process -> read ()) {
Log:: info ( ' TestProcess: read data ' , [ $ data ]);
$ process -> write ( ' TestProcess: ' . $ data );
}
}
// app/Http/Controllers/TestController.php
public function testProcessWrite ()
{
/**@var SwooleProcess[] $process */
$ customProcesses = Hhxsv5 LaravelS LaravelS:: getCustomProcesses ();
$ process = $ customProcesses [ ' test ' ];
$ process -> write ( ' TestController: write data ' . time ());
var_dump ( $ process -> read ());
}
LaravelS
akan menarik konfigurasiApollo
dan menulisnya ke file.env
saat memulai. Pada saat yang sama,LaravelS
akan memulai proses kustomapollo
untuk memantau konfigurasi dan secara otomatisreload
ketika konfigurasi berubah.
Aktifkan Apollo: tambahkan parameter --enable-apollo
dan Apollo ke parameter startup.
php bin/laravels start --enable-apollo --apollo-server=http://127.0.0.1:8080 --apollo-app-id=LARAVEL-S-TEST
Mendukung pembaruan terbaru (opsional).
// Edit `config/laravels.php`
' processes ' => Hhxsv5 LaravelS Components Apollo Process:: getDefinition (),
// When there are other custom process configurations
' processes ' => [
' test ' => [
' class ' => App Processes TestProcess::class,
' redirect ' => false ,
' pipe ' => 1 ,
],
// ...
] + Hhxsv5 LaravelS Components Apollo Process:: getDefinition (),
Daftar parameter yang tersedia.
Parameter | Keterangan | Bawaan | Demo |
---|---|---|---|
server apollo | URL server Apollo | - | --apollo-server=http://127.0.0.1:8080 |
apollo-app-id | ID APLIKASI Apollo | - | --apollo-app-id=Uji LARAVEL-S |
ruang nama apollo | Namespace tempat APP berada, dukungan menentukan kelipatannya | aplikasi | --apollo-namespaces=aplikasi --apollo-namespaces=env |
cluster apollo | Cluster tempat APP berada | bawaan | --apollo-cluster=default |
apollo-klien-ip | IP instance saat ini, juga dapat digunakan untuk penerbitan skala abu-abu | IP intranet lokal | --apollo-klien-ip=10.2.1.83 |
apollo-pull-timeout | Waktu habis (detik) saat menarik konfigurasi | 5 | --apollo-tarik-batas waktu=5 |
apollo-backup-lama-env | Apakah akan mencadangkan file konfigurasi lama saat memperbarui file konfigurasi .env | PALSU | --apollo-backup-old-env |
Mendukung pemantauan dan alarm Prometheus, Grafana melihat metrik pemantauan secara visual. Silakan merujuk ke Docker Compose untuk konstruksi lingkungan Prometheus dan Grafana.
Memerlukan ekstensi APCu >= 5.0.0, silakan instal dengan pecl install apcu
.
Salin file konfigurasi prometheus.php
ke direktori config
proyek Anda. Ubah konfigurasi seperlunya.
# Execute commands in the project root directory
cp vendor/hhxsv5/laravel-s/config/prometheus.php config/
Jika proyek Anda adalah Lumen
, Anda juga perlu memuat konfigurasi secara manual $app->configure('prometheus');
di bootstrap/app.php
.
Konfigurasikan middleware global
: Hhxsv5LaravelSComponentsPrometheusRequestMiddleware::class
. Untuk menghitung konsumsi waktu permintaan seakurat mungkin, RequestMiddleware
harus menjadi middleware global first
, yang perlu ditempatkan di depan middleware lainnya.
Daftarkan ServiceProvider: Hhxsv5LaravelSComponentsPrometheusServiceProvider::class
.
Konfigurasikan CollectorProcess di config/laravels.php
untuk mengumpulkan metrik proses Swoole Worker/Task/Timer secara teratur.
' processes ' => Hhxsv5 LaravelS Components Prometheus CollectorProcess:: getDefinition (),
Buat rute ke metrik keluaran.
use Hhxsv5 LaravelS Components Prometheus Exporter ;
Route:: get ( ' /actuator/prometheus ' , function () {
$ result = app (Exporter::class)-> render ();
return response ( $ result , 200 , [ ' Content-Type ' => Exporter:: REDNER_MIME_TYPE ]);
});
Selesaikan konfigurasi Prometheus dan mulai.
global :
scrape_interval : 5s
scrape_timeout : 5s
evaluation_interval : 30s
scrape_configs :
- job_name : laravel-s-test
honor_timestamps : true
metrics_path : /actuator/prometheus
scheme : http
follow_redirects : true
static_configs :
- targets :
- 127.0.0.1:5200 # The ip and port of the monitored service
# Dynamically discovered using one of the supported service-discovery mechanisms
# https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config
# - job_name: laravels-eureka
# honor_timestamps: true
# scrape_interval: 5s
# metrics_path: /actuator/prometheus
# scheme: http
# follow_redirects: true
# eureka_sd_configs:
# - server: http://127.0.0.1:8080/eureka
# follow_redirects: true
# refresh_interval: 5s
Mulai Grafana, lalu impor panel json.
Acara yang didukung:
Peristiwa | Antarmuka | Kapan itu terjadi |
---|---|---|
ServerMulai | Hhxsv5LaravelSSwooleEventsServerStartInterface | Terjadi ketika proses Master dimulai, this event should not handle complex business logic, and can only do some simple work of initialization . |
ServerBerhenti | Hhxsv5LaravelSSwooleEventsServerStopInterface | Terjadi ketika server keluar secara normal, CANNOT use async or coroutine related APIs in this event . |
PekerjaMulai | Hhxsv5LaravelSSwooleEventsWorkerStartInterface | Terjadi setelah proses Pekerja/Tugas dimulai, dan inisialisasi Laravel telah selesai. |
PekerjaBerhenti | Hhxsv5LaravelSSwooleEventsWorkerStopInterface | Terjadi setelah proses Pekerja/Tugas keluar secara normal |
Kesalahan Pekerja | Hhxsv5LaravelSSwooleEventsWorkerErrorInterface | Terjadi ketika terjadi pengecualian atau kesalahan fatal pada proses Pekerja/Tugas |
1.Buat kelas acara untuk mengimplementasikan antarmuka yang sesuai.
namespace App Events ;
use Hhxsv5 LaravelS Swoole Events ServerStartInterface ;
use Swoole Atomic ;
use Swoole Http Server ;
class ServerStartEvent implements ServerStartInterface
{
public function __construct ()
{
}
public function handle ( Server $ server )
{
// Initialize a global counter (available across processes)
$ server -> atomicCount = new Atomic ( 2233 );
// Invoked in controller: app('swoole')->atomicCount->get();
}
}
namespace App Events ;
use Hhxsv5 LaravelS Swoole Events WorkerStartInterface ;
use Swoole Http Server ;
class WorkerStartEvent implements WorkerStartInterface
{
public function __construct ()
{
}
public function handle ( Server $ server , $ workerId )
{
// Initialize a database connection pool
// DatabaseConnectionPool::init();
}
}
2.Konfigurasi.
// Edit `config/laravels.php`
' event_handlers ' => [
' ServerStart ' => [ App Events ServerStartEvent::class], // Trigger events in array order
' WorkerStart ' => [ App Events WorkerStartEvent::class],
],
Fungsi Hitung.
1.Modifikasi bootstrap/app.php
dan atur direktori penyimpanan. Karena direktori proyek bersifat read-only, direktori /tmp
hanya dapat dibaca dan ditulis.
$ app -> useStoragePath ( env ( ' APP_STORAGE_PATH ' , ' /tmp/storage ' ));
2.Buat skrip shell laravels_bootstrap
dan berikan executable permission
.
#! /usr/bin/env bash
set +e
# Create storage-related directories
mkdir -p /tmp/storage/app/public
mkdir -p /tmp/storage/framework/cache
mkdir -p /tmp/storage/framework/sessions
mkdir -p /tmp/storage/framework/testing
mkdir -p /tmp/storage/framework/views
mkdir -p /tmp/storage/logs
# Set the environment variable APP_STORAGE_PATH, please make sure it's the same as APP_STORAGE_PATH in .env
export APP_STORAGE_PATH=/tmp/storage
# Start LaravelS
php bin/laravels start
3.Konfigurasi template.xml
.
ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
laravel-s-demo:
Type: 'Aliyun::Serverless::Service'
Properties:
Description: 'LaravelS Demo for Serverless'
fc-laravel-s:
Type: 'Aliyun::Serverless::Function'
Properties:
Handler: laravels.handler
Runtime: custom
MemorySize: 512
Timeout: 30
CodeUri: ./
InstanceConcurrency: 10
EnvironmentVariables:
BOOTSTRAP_FILE: laravels_bootstrap
Dalam mode FPM, instance tunggal akan dibuat instance-nya dan didaur ulang di setiap permintaan, request start=>instance instance=>request end=>recycled instance.
Di bawah Swoole Server, Semua instance tunggal akan disimpan di memori, masa pakainya berbeda dari FPM, request start=>instansiate instance=>request end=>jangan mendaur ulang instance singleton. Jadi perlu pengembang untuk mempertahankan status instance tunggal di setiap permintaan.
Solusi umum:
Tulis kelas XxxCleaner
untuk membersihkan status objek tunggal. Kelas ini mengimplementasikan antarmuka Hhxsv5LaravelSIlluminateCleanersCleanerInterface
dan kemudian mendaftarkannya di cleaners
laravels.php
.
Reset
status instans tunggal oleh Middleware
.
Daftarkan ulang ServiceProvider
, tambahkan XxxServiceProvider
ke register_providers
file laravels.php
. Sehingga menginisialisasi ulang instance tunggal di setiap permintaan Referensi.
Pembersih konfigurasi.
Masalah yang diketahui: kumpulan masalah dan solusi yang diketahui.
Pencatatan; jika Anda ingin mengeluarkan keluaran ke konsol, Anda dapat menggunakan stderr
, Log::channel('stderr')->debug('debug message').
Laravel Dump Server(Laravel 5.7 telah terintegrasi secara default).
Permintaan baca oleh IlluminateHttpRequest
Object, $_ENV dapat dibaca, $_SERVER dapat dibaca sebagian, CANNOT USE
$_GET/$_POST/$_FILES/$_COOKIE/$_REQUEST/$_SESSION/$GLOBALS.
public function form ( Illuminate Http Request $ request )
{
$ name = $ request -> input ( ' name ' );
$ all = $ request -> all ();
$ sessionId = $ request -> cookie ( ' sessionId ' );
$ photo = $ request -> file ( ' photo ' );
// Call getContent() to get the raw POST body, instead of file_get_contents('php://input')
$ rawContent = $ request -> getContent ();
//...
}
Respons dengan IlluminateHttpResponse
Object, kompatibel dengan echo/vardump()/print_r(), CANNOT USE
fungsi dd()/exit()/die()/header()/setcookie()/http_response_code().
public function json ()
{
return response ()-> json ([ ' time ' => time ()])-> header ( ' header1 ' , ' value1 ' )-> withCookie ( ' c1 ' , ' v1 ' );
}
Singleton connection
akan disimpan di memori, disarankan untuk mengaktifkan persistent connection
untuk kinerja yang lebih baik.
will
terhubung kembali secara otomatis immediately
setelah terputus. // config/database.php
' connections ' => [
' my_conn ' => [
' driver ' => ' mysql ' ,
' host ' => env ( ' DB_MY_CONN_HOST ' , ' localhost ' ),
' port ' => env ( ' DB_MY_CONN_PORT ' , 3306 ),
' database ' => env ( ' DB_MY_CONN_DATABASE ' , ' forge ' ),
' username ' => env ( ' DB_MY_CONN_USERNAME ' , ' forge ' ),
' password ' => env ( ' DB_MY_CONN_PASSWORD ' , '' ),
' charset ' => ' utf8mb4 ' ,
' collation ' => ' utf8mb4_unicode_ci ' ,
' prefix ' => '' ,
' strict ' => false ,
' options ' => [
// Enable persistent connection
PDO :: ATTR_PERSISTENT => true ,
],
],
],
won't
tersambung kembali secara otomatis immediately
setelah terputus, dan akan memunculkan pengecualian tentang koneksi yang hilang, sambungkan kembali di lain waktu. Anda perlu memastikan bahwa SELECT DB
benar sebelum mengoperasikan Redis setiap saat. // config/database.php
' redis ' => [
' client ' => env ( ' REDIS_CLIENT ' , ' phpredis ' ), // It is recommended to use phpredis for better performance.
' default ' => [
' host ' => env ( ' REDIS_HOST ' , ' localhost ' ),
' password ' => env ( ' REDIS_PASSWORD ' , null ),
' port ' => env ( ' REDIS_PORT ' , 6379 ),
' database ' => 0 ,
' persistent ' => true , // Enable persistent connection
],
],
Hindari menggunakan variabel global. Jika perlu, bersihkan atau setel ulang secara manual.
Menambahkan elemen tanpa batas ke dalam variabel static
/ global
akan menyebabkan OOM (Kehabisan Memori).
class Test
{
public static $ array = [];
public static $ string = '' ;
}
// Controller
public function test ( Request $ req )
{
// Out of Memory
Test:: $ array [] = $ req -> input ( ' param1 ' );
Test:: $ string .= $ req -> input ( ' param2 ' );
}
Metode deteksi kebocoran memori
Ubah config/laravels.php
: worker_num=1, max_request=1000000
, ingatlah untuk mengubahnya kembali setelah pengujian;
Tambahkan perutean /debug-memory-leak
tanpa route middleware
untuk mengamati perubahan memori pada proses Worker
;
Route:: get ( ' /debug-memory-leak ' , function () {
global $ previous ;
$ current = memory_get_usage ();
$ stats = [
' prev_mem ' => $ previous ,
' curr_mem ' => $ current ,
' diff_mem ' => $ current - $ previous ,
];
$ previous = $ current ;
return $ stats ;
});
Mulai LaravelS
dan minta /debug-memory-leak
hingga diff_mem
kurang dari atau sama dengan nol; jika diff_mem
selalu lebih besar dari nol, berarti mungkin ada kebocoran memori di Global Middleware
atau Laravel Framework
;
Setelah menyelesaikan Step 3
, alternately
meminta rute bisnis dan /debug-memory-leak
(Disarankan menggunakan ab
/ wrk
untuk membuat permintaan rute bisnis dalam jumlah besar), peningkatan awal dalam memori adalah normal. Setelah sejumlah besar permintaan untuk rute bisnis, jika diff_mem
selalu lebih besar dari nol dan curr_mem
terus meningkat, ada kemungkinan besar kebocoran memori; Jika curr_mem
selalu berubah dalam rentang tertentu dan tidak terus meningkat, kemungkinan kebocoran memori kecil.
Jika masih belum bisa menyelesaikannya, max_request adalah jaminan terakhir.
Penyesuaian parameter kernel Linux
Tes tekanan
PayPal
BTC
gitee
MIT