() translation by (you can also view the original English article)
In diesem Artikel werden wir die Warteschlangen-API im Laravel-Web-Framework untersuchen. Es ermöglicht Ihnen, ressourcenintensive Aufgaben während der Skriptausführung zu verschieben, um die allgemeine Endbenutzererfahrung zu verbessern. Nachdem ich die grundlegende Terminologie vorgestellt habe, demonstriere ich sie anhand eines realen Beispiels.
Die Seitenladezeit ist ein wichtiger Aspekt jeder erfolgreichen Website, und man sollte nicht die Bedeutung dieser Website übersehen, da sie sich auf die SEO der Website und die allgemeine Endbenutzererfahrung auswirkt. In den meisten Fällen müssen Sie Webseiten mit langen Seitenladezeiten debuggen. Natürlich gibt es verschiedene Ansätze, die Sie verwenden könnten, um dieses Problem zu beheben.
Bei der Untersuchung stellen Sie häufig fest, dass bestimmte Code-Blöcke die Ausführung der Seite verzögern. Das nächste, was Sie versuchen könnten, ist das Identifizieren von Blöcken, die zur Verarbeitung zurückgestellt werden können und keinen wirklichen Einfluss auf das Endergebnis der aktuellen Seite haben. Das sollte die Gesamtgeschwindigkeit der Webseite wirklich verbessern, da wir Code-Blöcke eliminiert haben, die eine Verzögerung verursacht haben.
Heute werden wir ein ähnliches Konzept im Zusammenhang mit dem Laravel-Web-Framework untersuchen. In der Tat bietet Laravel bereits eine nützliche integrierte API, mit der wir die Verarbeitung von Aufgaben verzögern können - die Queue-API. Ohne viel Zeit zu verschwenden, werde ich die grundlegenden Elemente der Queue API besprechen.
Treiber, Verbindungen, Warteschlangen und Jobs
Der grundlegende Zweck der Warteschlangen-API besteht darin, Jobs auszuführen, die in einer Warteschlange hinzugefügt werden. Als nächstes könnte die Warteschlange zu einer bestimmten Verbindung gehören, und diese Verbindung könnte zu einem bestimmten Warteschlangentreiber gehören, der selbst mit dieser Verbindung konfiguriert ist. Versuchen wir kurz zu verstehen, was ich gerade gesagt habe.
Queue Drivers
Genauso wie Sie einen anderen Treiber für Ihre Datenbankverbindung verwendet hätten, könnten Sie auch aus einer Reihe verschiedener Warteschlangentreiber auswählen. Die Queue API unterstützt verschiedene Adapter wie database, beanstalkd, sqs und redis.
Der Warteschlangentreiber ist nur ein Ort, an dem Informationen zur Warteschlange gespeichert werden. Wenn Sie beispielsweise einen Datenbankwarteschlangentreiber verwenden, wird der neue Job in der Jobtabelle in der Datenbank hinzugefügt. Wenn Sie andererseits redis als Standardwarteschlangentreiber konfiguriert haben, wird der Job dem Redis-Server hinzugefügt.
Die Queue API bietet außerdem zwei spezielle Warteschlangentreiber für Testzwecke - sync und null. Der Synchronisierungswarteschlangentreiber wird verwendet, um einen Warteschlangenauftrag sofort auszuführen, während der Nullwarteschlangentreiber zum Überspringen eines Auftrags verwendet wird, sodass er überhaupt nicht ausgeführt wird.
Connections
Wenn Sie die Queue API zum ersten Mal konfigurieren, müssen Sie eine Standardverbindung angeben, die für die Verarbeitung der Standardwarteschlange verwendet werden soll. Zumindest wird erwartet, dass die Verbindung folgende Informationen liefert:
- der Warteschlangentreiber, der verwendet wird
- die spezifischen Konfigurationswerte des Warteschlangentreibers
- Der Name der Standardwarteschlange, in der der Job hinzugefügt wird
Queues
Wenn Sie einen Job zu einer Warteschlange hinzufügen, wird er zur Standardwarteschlange hinzugefügt. In der Tat sollte das in den meisten Fällen in Ordnung sein, es sei denn, Sie haben Jobs, denen gegenüber anderen Jobs eine höhere Priorität eingeräumt werden muss. In diesem Fall könnten Sie eine Warteschlange mit dem Namen "hoch" erstellen und die Jobs mit der höheren Priorität in dieser bestimmten Warteschlange platzieren.
Wenn Sie einen Warteschlangen-Worker ausführen, der in der Warteschlange befindliche Jobs verarbeitet, können Sie optional den Parameter --queue
übergeben, mit dem Sie Warteschlangennamen in der Reihenfolge auflisten können, in der sie verarbeitet werden müssen. Wenn Sie beispielsweise --queue=high,default
, angeben, werden zuerst die Jobs in der hohen Warteschlange verarbeitet und nach Abschluss der Jobs werden Jobs in der Standardwarteschlange abgerufen.
Jobs
Ein Job in der Queue API ist eine Aufgabe, die vom Hauptausführungsfluss zurückgestellt wird. Wenn Sie beispielsweise ein Thumbnail erstellen möchten, während der Benutzer ein Bild vom Front-End hochlädt, können Sie einen neuen Job erstellen, der die Thumbnail-Verarbeitung verarbeitet. Auf diese Weise können Sie die Aufgabe der Miniaturbildverarbeitung aus dem Hauptausführungsfluss zurückstellen.
Das war eine grundlegende Einführung in die Queue API-Terminologie. Ab dem nächsten Abschnitt erfahren Sie, wie Sie einen benutzerdefinierten Warteschlangenauftrag erstellen und ihn mit einem Laravel-Warteschlangen-Worker ausführen.
Erstellen Sie Ihren ersten Warteschlangenauftrag
Jetzt sollten Sie sich über Warteschlangenaufträge sicher sein. Von diesem Abschnitt an werden wir ein reales Beispiel implementieren, das das Konzept von Warteschlangen-Jobs in Laravel demonstriert.
In den meisten Fällen landen Sie in der Situation, in der Sie verschiedene Miniaturversionen eines Bildes erstellen müssen, das von einem Benutzer hochgeladen wurde. In den meisten Fällen versucht der Entwickler, es in Echtzeit zu verarbeiten, sodass verschiedene Versionen von Bildern sofort erstellt werden, wenn der Benutzer ein Bild hochlädt.
Es scheint ein vernünftiger Ansatz zu sein, wenn Sie ein paar Versionen erstellen und es nicht zu viel Zeit in Anspruch nimmt. Auf der anderen Seite, wenn Sie mit einer Anwendung zu tun haben, die eine starke Verarbeitung erfordert und dadurch mehr Ressourcen verbraucht, könnte die Verarbeitung in Echtzeit zu einer schlechten Benutzererfahrung führen.
Die offensichtliche Option, die Ihnen zuerst in den Sinn kommt, ist, die Verarbeitung der Thumbnail-Generierung so spät wie möglich zu verschieben. Der einfachste Ansatz, den Sie in diesem speziellen Szenario implementieren könnten, besteht darin, einen Cron-Job festzulegen, der die Verarbeitung in regelmäßigen Intervallen auslöst, und Ihnen sollte nichts passieren.
Ein viel besserer Ansatz besteht dagegen darin, die Aufgabe aufzuschieben und in eine Warteschlange zu schieben, und sie von der Warteschlangenmitarbeiterin verarbeiten zu lassen, wenn sie dazu in der Lage ist. In einer Produktionsumgebung ist der Warteschlangen-Worker ein Daemon-Skript, das Aufgaben in einer Warteschlange ausführt und verarbeitet. Der offensichtliche Vorteil dieses Ansatzes ist eine viel bessere Endbenutzererfahrung, und Sie müssen nicht auf den Cron-Lauf warten, da der Job so schnell wie möglich verarbeitet wird.
Ich denke, das ist genug Theorie, um mit einer tatsächlichen Implementierung zu beginnen.
In unserem Fall werden wir den database
-Warteschlangentreiber verwenden, und wir müssen die jobs
-Tabelle in der Datenbank erstellen. Die jobs-Tabelle enthält alle jobs
, die bei der nächsten Ausführung des Warteschlangen-Workers verarbeitet werden müssen.
Bevor wir fortfahren und die jobs
-Tabelle erstellen, ändern wir die Standardwarteschlangenkonfiguration von sync
in database
in der Datei config/queue.php
.
1 |
...
|
2 |
...
|
3 |
/*
|
4 |
|--------------------------------------------------------------------------
|
5 |
| Default Queue Driver
|
6 |
|--------------------------------------------------------------------------
|
7 |
|
|
8 |
| Laravel's queue API supports an assortment of back-ends via a single
|
9 |
| API, giving you convenient access to each back-end using the same
|
10 |
| syntax for each one. Here you may set the default queue driver.
|
11 |
|
|
12 |
| Supported: "sync", "database", "beanstalkd", "sqs", "redis", "null"
|
13 |
|
|
14 |
*/
|
15 |
|
16 |
'default' => env('QUEUE_DRIVER', 'database'), |
17 |
...
|
18 |
...
|
In der Tat bietet Laravel bereits einen handwerklichen Befehl, der uns hilft, die jobs
-Tabelle zu erstellen. Führen Sie den folgenden Befehl im Stammverzeichnis Ihrer Laravel-Anwendung aus, und erstellen Sie die erforderliche Datenbankmigration, mit der die jobs
-Tabelle erstellt wird.
1 |
$php artisan queue:table |
Die Migrationsdatei, die in database/migrations/YYYY_MM_DD_HHMMSS_create_jobs_table.php
generiert wird, sollte folgendermaßen aussehen:
1 |
<?php
|
2 |
use Illuminate\Support\Facades\Schema; |
3 |
use Illuminate\Database\Schema\Blueprint; |
4 |
use Illuminate\Database\Migrations\Migration; |
5 |
|
6 |
class CreateJobsTable extends Migration |
7 |
{
|
8 |
/**
|
9 |
* Run the migrations.
|
10 |
*
|
11 |
* @return void
|
12 |
*/
|
13 |
public function up() |
14 |
{
|
15 |
Schema::create('jobs', function (Blueprint $table) { |
16 |
$table->bigIncrements('id'); |
17 |
$table->string('queue'); |
18 |
$table->longText('payload'); |
19 |
$table->unsignedTinyInteger('attempts'); |
20 |
$table->unsignedInteger('reserved_at')->nullable(); |
21 |
$table->unsignedInteger('available_at'); |
22 |
$table->unsignedInteger('created_at'); |
23 |
|
24 |
$table->index(['queue', 'reserved_at']); |
25 |
});
|
26 |
}
|
27 |
|
28 |
/**
|
29 |
* Reverse the migrations.
|
30 |
*
|
31 |
* @return void
|
32 |
*/
|
33 |
public function down() |
34 |
{
|
35 |
Schema::dropIfExists('jobs'); |
36 |
}
|
37 |
}
|
Als nächstes führen wir den migrate
-Befehl aus, so dass er tatsächlich die jobs
-Tabelle in einer Datenbank erstellt.
1 |
php artisan migrate |
Soweit die jobs
-Migration betroffen ist.
Als Nächstes erstellen wir das Image
-Modell, mit dem die vom Endbenutzer hochgeladenen Bilder verwaltet werden. Das Image-Modell benötigt außerdem eine zugeordnete Datenbanktabelle. Daher verwenden wir beim Erstellen des Image
-Modells die Option --migrate
.
1 |
php artisan make:model Image --migration |
Der obige Befehl sollte die Image
-Modellklasse und eine zugehörige Datenbankmigration ebenfalls erstellen.
Die Image
-Modellklasse sollte folgendermaßen aussehen:
1 |
<?php
|
2 |
// app/Image.php
|
3 |
namespace App; |
4 |
|
5 |
use Illuminate\Database\Eloquent\Model; |
6 |
|
7 |
class Image extends Model |
8 |
{
|
9 |
//
|
10 |
}
|
Die Datenbankmigrationsdatei sollte unter database/migrations/YYYY_MM_DD_HHMMSS_create_images_table.php
erstellt werden. Wir möchten auch den ursprünglichen Pfad des vom Endbenutzer hochgeladenen Bildes speichern. Lassen Sie uns den Code der Image
-Datenbankmigrationsdatei so ändern, dass er wie folgt aussieht.
1 |
<?php
|
2 |
// database/migrations/YYYY_MM_DD_HHMMSS_create_images_table.php
|
3 |
use Illuminate\Support\Facades\Schema; |
4 |
use Illuminate\Database\Schema\Blueprint; |
5 |
use Illuminate\Database\Migrations\Migration; |
6 |
|
7 |
class CreateImagesTable extends Migration |
8 |
{
|
9 |
/**
|
10 |
* Run the migrations.
|
11 |
*
|
12 |
* @return void
|
13 |
*/
|
14 |
public function up() |
15 |
{
|
16 |
Schema::create('images', function (Blueprint $table) { |
17 |
$table->increments('id'); |
18 |
$table->timestamps(); |
19 |
$table->string('org_path'); |
20 |
});
|
21 |
}
|
22 |
|
23 |
/**
|
24 |
* Reverse the migrations.
|
25 |
*
|
26 |
* @return void
|
27 |
*/
|
28 |
public function down() |
29 |
{
|
30 |
Schema::dropIfExists('images'); |
31 |
}
|
32 |
}
|
Wie Sie sehen, haben wir die Spalte $table->string('org_path')
hinzugefügt, um den Pfad des Originalbildes zu speichern. Als Nächstes müssen Sie nur den Befehl migrate
ausführen, um diese Tabelle in der Datenbank zu erstellen.
1 |
$php artisan migrate |
Und das ist es, was das Image
-Modell angeht.
Erstellen Sie als Nächstes einen tatsächlichen Warteschlangenauftrag, der für die Verarbeitung von Miniaturbildern verantwortlich ist. Für die Miniaturbildverarbeitung verwenden wir eine sehr beliebte Bildverarbeitungsbibliothek - Interventionsbild.
Um die Intervention Image-Bibliothek zu installieren, führen Sie den folgenden Befehl im Stammverzeichnis Ihrer Anwendung aus.
1 |
$php composer.phar require intervention/image |
Jetzt ist es an der Zeit, die Job
-Klasse zu erstellen, und dazu verwenden wir einen Handwerkerbefehl.
1 |
$php artisan make:job ProcessImageThumbnails |
Das sollte die Job
-Klassenvorlage unter app/Jobs/ProcessImageThumbnails.php
erstellen. Lassen Sie uns den Inhalt dieser Datei ersetzen
1 |
<?php
|
2 |
// app/Jobs/ProcessImageThumbnails.php
|
3 |
namespace App\Jobs; |
4 |
|
5 |
use App\Image as ImageModel; |
6 |
use Illuminate\Bus\Queueable; |
7 |
use Illuminate\Queue\SerializesModels; |
8 |
use Illuminate\Queue\InteractsWithQueue; |
9 |
use Illuminate\Contracts\Queue\ShouldQueue; |
10 |
use Illuminate\Foundation\Bus\Dispatchable; |
11 |
use Illuminate\Support\Facades\DB; |
12 |
|
13 |
class ProcessImageThumbnails implements ShouldQueue |
14 |
{
|
15 |
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; |
16 |
|
17 |
protected $image; |
18 |
|
19 |
/**
|
20 |
* Create a new job instance.
|
21 |
*
|
22 |
* @return void
|
23 |
*/
|
24 |
public function __construct(ImageModel $image) |
25 |
{
|
26 |
$this->image = $image; |
27 |
}
|
28 |
|
29 |
/**
|
30 |
* Execute the job.
|
31 |
*
|
32 |
* @return void
|
33 |
*/
|
34 |
public function handle() |
35 |
{
|
36 |
// access the model in the queue for processing
|
37 |
$image = $this->image; |
38 |
$full_image_path = public_path($image->org_path); |
39 |
$resized_image_path = public_path('thumbs' . DIRECTORY_SEPARATOR . $image->org_path); |
40 |
|
41 |
// create image thumbs from the original image
|
42 |
$img = \Image::make($full_image_path)->resize(300, 200); |
43 |
$img->save($resized_image_path); |
44 |
}
|
45 |
}
|
Wenn der Warteschlangen-Worker beginnt, einen Job zu verarbeiten, sucht er nach der Handle
-Methode. Es ist also die Handle
-Methode, die die Hauptlogik Ihres Jobs enthält.
In unserem Fall müssen wir ein Thumbnail eines Bildes erstellen, das vom Benutzer hochgeladen wurde. Der Code der handle
-Methode ist ziemlich einfach: Wir rufen ein Image aus dem ImageModel
-Modell ab und erstellen ein Thumbnail mithilfe der Interventions-Image-Bibliothek. Natürlich müssen wir das entsprechende Image
-Modell übergeben, wenn wir unseren Job versenden, und wir werden es gleich sehen.
Um unseren neu erstellten Job zu testen, erstellen wir ein einfaches Upload-Formular, mit dem der Benutzer ein Bild hochladen kann. Natürlich werden wir keine Vorschaubilder erstellen. Wir verschieben diese Aufgabe, damit sie vom Warteschlangenarbeiter verarbeitet werden kann.
Lassen Sie uns eine Controller-Datei unter app/Http/Controllers/ImageController.php
erstellen, wie unten gezeigt.
1 |
<?php
|
2 |
namespace App\Http\Controllers; |
3 |
|
4 |
use App\Image; |
5 |
use App\Jobs\ProcessImageThumbnails; |
6 |
use Illuminate\Http\Request; |
7 |
use Illuminate\Support\Facades\Redirect; |
8 |
use App\Http\Controllers\Controller; |
9 |
use Validator; |
10 |
|
11 |
class ImageController extends Controller |
12 |
{
|
13 |
/**
|
14 |
* Show Upload Form
|
15 |
*
|
16 |
* @param Request $request
|
17 |
* @return Response
|
18 |
*/
|
19 |
public function index(Request $request) |
20 |
{
|
21 |
return view('upload_form'); |
22 |
}
|
23 |
|
24 |
/**
|
25 |
* Upload Image
|
26 |
*
|
27 |
* @param Request $request
|
28 |
* @return Response
|
29 |
*/
|
30 |
public function upload(Request $request) |
31 |
{
|
32 |
// upload image
|
33 |
$this->validate($request, [ |
34 |
'demo_image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048', |
35 |
]);
|
36 |
$image = $request->file('demo_image'); |
37 |
$input['demo_image'] = time().'.'.$image->getClientOriginalExtension(); |
38 |
$destinationPath = public_path('/images'); |
39 |
$image->move($destinationPath, $input['demo_image']); |
40 |
|
41 |
// make db entry of that image
|
42 |
$image = new Image; |
43 |
$image->org_path = 'images' . DIRECTORY_SEPARATOR . $input['demo_image']; |
44 |
$image->save(); |
45 |
|
46 |
// defer the processing of the image thumbnails
|
47 |
ProcessImageThumbnails::dispatch($image); |
48 |
|
49 |
return Redirect::to('image/index')->with('message', 'Image uploaded successfully!'); |
50 |
}
|
51 |
}
|
Lassen Sie uns eine zugehörige View-Datei unter resources/views/upload_form.blade.php
erstellen.
1 |
<!DOCTYPE html>
|
2 |
<html lang="{{ config('app.locale') }}"> |
3 |
<head>
|
4 |
<meta charset="utf-8"> |
5 |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
6 |
<meta name="viewport" content="width=device-width, initial-scale=1"> |
7 |
<meta name="csrf-token" content="{{ csrf_token() }}" /> |
8 |
<title>Laravel</title> |
9 |
|
10 |
<!-- Fonts -->
|
11 |
<link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css"> |
12 |
|
13 |
<!-- Styles -->
|
14 |
<style>
|
15 |
html, body { |
16 |
background-color: #fff; |
17 |
color: #636b6f; |
18 |
font-family: 'Raleway', sans-serif; |
19 |
font-weight: 100; |
20 |
height: 100vh; |
21 |
margin: 0; |
22 |
}
|
23 |
|
24 |
.full-height { |
25 |
height: 100vh; |
26 |
}
|
27 |
|
28 |
.flex-center { |
29 |
align-items: center; |
30 |
display: flex; |
31 |
justify-content: center; |
32 |
}
|
33 |
|
34 |
.position-ref { |
35 |
position: relative; |
36 |
}
|
37 |
|
38 |
.top-right { |
39 |
position: absolute; |
40 |
right: 10px; |
41 |
top: 18px; |
42 |
}
|
43 |
|
44 |
.content { |
45 |
text-align: center; |
46 |
}
|
47 |
|
48 |
.title { |
49 |
font-size: 84px; |
50 |
}
|
51 |
|
52 |
.links > a { |
53 |
color: #636b6f; |
54 |
padding: 0 25px; |
55 |
font-size: 12px; |
56 |
font-weight: 600; |
57 |
letter-spacing: .1rem; |
58 |
text-decoration: none; |
59 |
text-transform: uppercase; |
60 |
}
|
61 |
|
62 |
.m-b-md { |
63 |
margin-bottom: 30px; |
64 |
}
|
65 |
|
66 |
.alert { |
67 |
color: red; |
68 |
font-weight: bold; |
69 |
margin: 10px; |
70 |
}
|
71 |
.success { |
72 |
color: blue; |
73 |
font-weight: bold; |
74 |
margin: 10px; |
75 |
}
|
76 |
</style>
|
77 |
</head>
|
78 |
<body>
|
79 |
<div class="flex-center position-ref full-height"> |
80 |
@if (Route::has('login')) |
81 |
<div class="top-right links"> |
82 |
@if (Auth::check()) |
83 |
<a href="{{ url('/home') }}">Home</a> |
84 |
@else |
85 |
<a href="{{ url('/login') }}">Login</a> |
86 |
<a href="{{ url('/register') }}">Register</a> |
87 |
@endif |
88 |
</div>
|
89 |
@endif |
90 |
|
91 |
<div class="content"> |
92 |
<div class="m-b-md"> |
93 |
<h1 class="title">Demo Upload Form</h1> |
94 |
|
95 |
@if ($errors->any()) |
96 |
<div class="alert alert-danger"> |
97 |
<ul>
|
98 |
@foreach ($errors->all() as $error) |
99 |
<li>{{ $error }}</li> |
100 |
@endforeach |
101 |
</ul>
|
102 |
</div>
|
103 |
@endif |
104 |
|
105 |
@if (session('message')) |
106 |
<div class="success"> |
107 |
{{ session('message') }} |
108 |
</div>
|
109 |
@endif |
110 |
|
111 |
<form method="post" action="{{ url('/image/upload') }}" enctype="multipart/form-data"> |
112 |
<div>
|
113 |
<input type="file" name="demo_image" /> |
114 |
</div>
|
115 |
<br/>
|
116 |
<div>
|
117 |
<input type="hidden" name="_token" value="{{ csrf_token() }}"> |
118 |
<input type="submit" value="Upload Image"/> |
119 |
</div>
|
120 |
</form>
|
121 |
</div>
|
122 |
</div>
|
123 |
</div>
|
124 |
</body>
|
125 |
</html>
|
Abschließend fügen wir Routen für die Aktionen index
und upload
in der Datei routes/web.php
hinzu.
1 |
Route::get('image/index', 'ImageController@index'); |
2 |
Route::post('image/upload', 'ImageController@upload'); |
Im ImageController-
Controller wird die index
-Methode zum Rendern eines Upload-Formulars verwendet.
1 |
public function index(Request $request) |
2 |
{
|
3 |
return view('upload_form'); |
4 |
}
|
Wenn der Benutzer ein Formular sendet, wird die Upload
-Methode aufgerufen.
1 |
public function upload(Request $request) |
2 |
{
|
3 |
// upload image
|
4 |
$this->validate($request, [ |
5 |
'demo_image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048', |
6 |
]);
|
7 |
$image = $request->file('demo_image'); |
8 |
$input['demo_image'] = time().'.'.$image->getClientOriginalExtension(); |
9 |
$destinationPath = public_path('/images'); |
10 |
$image->move($destinationPath, $input['demo_image']); |
11 |
|
12 |
// make db entry of that image
|
13 |
$image = new Image; |
14 |
$image->org_path = 'images' . DIRECTORY_SEPARATOR . $input['demo_image']; |
15 |
$image->save(); |
16 |
|
17 |
// defer the processing of the image thumbnails
|
18 |
ProcessImageThumbnails::dispatch($image); |
19 |
|
20 |
return Redirect::to('image/index')->with('message', 'Image uploaded successfully!'); |
21 |
}
|
Zu Beginn der upload
-Methode werden Sie den üblichen Code zum Hochladen von Dateien bemerken, der die hochgeladene Datei in das public/images
-Verzeichnis verschiebt. Als Nächstes fügen wir einen Datenbankeintrag mit dem App/Image
-Modell ein.
Schließlich verwenden wir den Job ProcessImageThumbnails
, um die Verarbeitung der Thumbnail-Verarbeitung zu verschieben. Es ist wichtig zu beachten, dass es die dispatch
-Methode ist, die verwendet wird, um eine Aufgabe zu verschieben. Am Ende wird der Benutzer mit einer Erfolgsmeldung auf die Upload-Seite weitergeleitet.
Zu diesem Zeitpunkt wird der Job der jobs
-Tabelle zur Verarbeitung hinzugefügt. Lassen Sie es uns bestätigen, indem Sie die folgende Abfrage ausführen.
1 |
mysql> select * FROM lvl_jobs; |
2 |
| 1 | default | {"displayName":"App\\Jobs\\ProcessImageThumbnails","job":"Illuminate\\Queue\\CallQueuedHandler@call","maxTries":null,"timeout":null,"data":{"commandName":"App\\Jobs\\ProcessImageThumbnails","command":"O:31:\"App\\Jobs\\ProcessImageThumbnails\":5:{s:8:\"\u0000*\u0000image\";O:45:\"Illuminate\\Contracts\\Database\\ModelIdentifier\":2:{s:5:\"class\";s:9:\"App\\Image\";s:2:\"id\";i:2;}s:6:\"\u0000*\u0000job\";N;s:10:\"connection\";N;s:5:\"queue\";N;s:5:\"delay\";N;}"}} | 0 | NULL | 1510219099 | 1510219099 | |
Sie müssen sich fragen, was es braucht, um einen Job dann zu verarbeiten? Keine Sorge - darüber werden wir im nächsten Abschnitt sprechen.
Queue Worker
Die Aufgabe des Laravel-Warteschlangenarbeiters besteht darin, Jobs zu verarbeiten, die zur Verarbeitung in der Warteschlange stehen. In der Tat gibt es einen Handwerkerbefehl, der uns hilft, den Warteschlangen-Worker-Prozess zu starten.
1 |
$php artisan queue:work |
Sobald Sie diesen Befehl ausführen, werden ausstehende Jobs verarbeitet. In unserem Fall sollte es den Job ProcessImageThumbnails
verarbeiten, der in die Warteschlange gestellt wurde, als der Benutzer ein Bild früher hochgeladen hat.
1 |
$php artisan queue:work |
2 |
[YYYY-MM-DD HHMMSS] Processing: App\Jobs\ProcessImageThumbnails |
3 |
[YYYY-MM-DD HHMMSS] Processed: App\Jobs\ProcessImageThumbnails |
Sie hätten bemerkt, dass wenn Sie einen Warteschlangen-Worker starten, dieser so lange ausgeführt wird, bis Sie ihn manuell beenden oder das Terminal schließen. Tatsächlich wartet es darauf, dass der nächste Job verarbeitet wird. Sobald sich ein neuer Job in der Warteschlange befindet, wird er sofort verarbeitet, wenn der Warteschlangen-Worker ausgeführt wird.
Natürlich können wir es nicht so laufen lassen, also müssen wir einen Weg finden, wie der Warteschlangenarbeiter permanent im Hintergrund läuft.
Zu unserer Rettung gibt es mehrere Tools zur Prozessverwaltung, aus denen Sie auswählen können. Um einige zu nennen, hier ist eine Liste:
- Circus
- daemontools
- Monit
- Supervisor
- Upstart
Sie sollten ein Werkzeug wählen, mit dem Sie den Laravel Queue Worker verwalten können. Grundsätzlich möchten wir sicherstellen, dass der Warteschlangen-Worker unbegrenzt ausgeführt werden sollte, damit er in der Warteschlange befindliche Jobs sofort verarbeitet.
Das ist also die Queue API. Sie können es in Ihrer täglichen Entwicklung verwenden, um zeitraubende Aufgaben zur Verbesserung der Endbenutzererfahrung aufzuschieben.
Fazit
In diesem Artikel haben wir die Queue API in Laravel besprochen, was sehr hilfreich ist, wenn Sie die Verarbeitung von ressourcenintensiven Aufgaben verzögern möchten.
Wir begannen mit einer grundlegenden Einführung in die Queue API, die eine Diskussion über Verbindungen, Warteschlangen und Jobs beinhaltete. In der zweiten Hälfte des Artikels haben wir einen benutzerdefinierten Warteschlangenjob erstellt, der demonstriert, wie Sie die Queue API in der realen Welt verwenden können.
Für diejenigen unter Ihnen, die gerade mit Laravel anfangen oder Ihr Wissen, Ihre Website oder Ihre Anwendung mit Erweiterungen erweitern möchten, haben wir eine Vielzahl von Dingen, die Sie in Envato Market studieren können.
Fühlen Sie sich frei, das Feedback-Formular unten zu verwenden, um Ihre Fragen und Vorschläge zu posten.