Traitement des opérations lentes
Parfois, nous devons traiter des opérations lentes pour éviter qu'elles n'affectent le traitement des autres requêtes dans webman. Ces opérations peuvent être traitées selon différentes solutions selon la situation.
Option 1 : Utilisation de files d'attente de messages
Voir file d'attente Redis file d'attente Stomp
Avantages
Peut gérer des pics soudains de demandes de traitement
Inconvénients
Impossible de retourner directement les résultats au client. Si la diffusion des résultats est nécessaire, elle doit être coordonnée avec d'autres services, par exemple l'utilisation de webman/push pour diffuser les résultats du traitement.
Option 2 : Ajout d'un nouveau port HTTP
Ajout d'un nouveau port HTTP pour traiter les requêtes lentes. Ces requêtes lentes sont traitées par un groupe spécifique de processus via l'accès à ce port, et les résultats sont renvoyés directement au client après le traitement.
Avantages
Peut renvoyer directement les données au client
Inconvénients
Impossible de gérer des pics soudains de demandes
Étapes de mise en œuvre
Ajoutez la configuration suivante dans config/process.php.
return [
// ... Autres configurations omises ici ...
'task' => [
'handler' => \Webman\App::class,
'listen' => 'http://0.0.0.0:8686',
'count' => 8, // Nombre de processus
'user' => '',
'group' => '',
'reusePort' => true,
'constructor' => [
'requestClass' => \support\Request::class, // Configuration de la classe de requête
'logger' => \support\Log::channel('default'), // Instance du logger
'appPath' => app_path(), // Emplacement du répertoire app
'publicPath' => public_path() // Emplacement du répertoire public
]
]
];
Ainsi, les interfaces lentes peuvent transiter par le groupe de processus sur http://127.0.0.1:8686/ sans affecter le traitement des autres processus.
Pour que le frontend ne perçoive pas la différence de port, vous pouvez ajouter un proxy vers le port 8686 dans nginx. Si les chemins des requêtes lentes commencent tous par /task, la configuration nginx serait similaire à ce qui suit :
upstream webman {
server 127.0.0.1:8787;
keepalive 10240;
}
# Ajouter un nouvel upstream 8686
upstream task {
server 127.0.0.1:8686;
keepalive 10240;
}
server {
server_name webman.com;
listen 80;
access_log off;
root /path/webman/public;
# Les requêtes commençant par /task sont dirigées vers le port 8686, modifiez /task selon le préfixe nécessaire
location /task {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://task;
}
# Les autres requêtes passent par le port 8787 d'origine
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Connection "";
if (!-f $request_filename){
proxy_pass http://webman;
}
}
}
Ainsi, lorsque le client accède à domaine.com/task/xxx, la requête sera traitée par le port 8686 distinct sans affecter le traitement des requêtes sur le port 8787.
Option 3 : Utilisation de HTTP Chunked pour l'envoi asynchrone de données segmentées
Avantages
Peut renvoyer directement les données au client
Installation de workerman/http-client
composer require workerman/http-client
app/controller/IndexController.php
<?php
namespace app\controller;
use support\Request;
use support\Response;
use Workerman\Protocols\Http\Chunk;
class IndexController
{
public function index(Request $request)
{
$connection = $request->connection;
$http = new \Workerman\Http\Client();
$http->get('https://example.com/', function ($response) use ($connection) {
$connection->send(new Chunk($response->getBody()));
$connection->send(new Chunk('')); // Envoyer un chunk vide pour indiquer la fin de la réponse
});
// Envoyer d'abord les en-têtes HTTP, les données sont envoyées de manière asynchrone
return response()->withHeaders([
"Transfer-Encoding" => "chunked",
]);
}
}
Remarque
Cet exemple utilise le clientworkerman/http-clientpour récupérer de manière asynchrone les résultats HTTP et renvoyer les données. Vous pouvez également utiliser d'autres clients asynchrones tels que AsyncTcpConnection.