Heim  >  Artikel  >  PHP-Framework  >  Wie verwende ich ThinkPHP6 für asynchrone Protokollierungsvorgänge?

Wie verwende ich ThinkPHP6 für asynchrone Protokollierungsvorgänge?

WBOY
WBOYOriginal
2023-06-12 09:57:112160Durchsuche

Mit der rasanten Entwicklung des Internets sind Protokollierungsdienste zu einem unverzichtbaren Modul für jede große Webanwendung geworden. Um verschiedene Anforderungen wie Fehlersuche und Leistungsüberwachung zu erfüllen, wird in diesem Artikel erläutert, wie Sie mit dem ThinkPHP6-Framework asynchrone Protokollierungsvorgänge durchführen.

1. Was ist Protokollierung? In der Informatik bezieht sich Protokollierung auf die Aufzeichnung von Ereignissen und Informationen, die in einem Computersystem auftreten. Typischerweise werden diese Datensätze in Dateien oder Datenbanken gespeichert. Die Protokollierung hilft, den Betriebsstatus des Systems zu verstehen, Probleme rechtzeitig zu erkennen und zu lösen und dadurch die Zuverlässigkeit und Stabilität des Systems zu verbessern.

In Webanwendungen kann die Protokollierung Entwicklern helfen, die Probleme und Fehler, auf die das System stößt, besser zu verstehen. Anhand der Protokollierung können Entwickler das Verhalten der Anwendung klar nachvollziehen und erkennen, wo und wann Fehler auftreten.

2. ThinkPHP6 asynchrone Protokollierung

Im Anwendungsentwicklungsprozess ist die Protokollierung ein wesentliches Modul. Darüber hinaus ist die Protokollierung häufig ein zeitaufwändiger Vorgang, der sich bei synchroner Ausführung auf die Systemleistung auswirken kann. Zu diesem Zweck führt ThinkPHP6 die Funktion der asynchronen Protokollierung ein, sodass die Protokollierung die Reaktionsgeschwindigkeit der Anwendung nicht mehr beeinträchtigt.

Normalerweise protokollieren wir den Controller oder das Modell. Um dies zu erreichen, verwenden wir die injizierte PsrLogLoggerInterface-Schnittstelle.

// Controller或Model中
use PsrLogLoggerInterface;

public function index(LoggerInterface $logger){
    $logger->info('hello world');
}

Einfach zu bedienen. Verwenden Sie die asynchrone Protokollierung, um einen asynchronen Logger zu definieren: PsrLogLoggerInterface 接口来实现。

use MonologLogger;
use MonologHandlerStreamHandler;

$logger=new Logger("AsyncLogger");
$logger->pushHandler(new StreamHandler('runtime/log/async.log'), Logger::INFO);

简单的使用方式。使用异步日志记录,定义一个异步日志记录器:

// Message类
namespace appcommon;

class Message
{
    /**
     * 记录日志
     * @param $level
     * @param $message
     * @param array $context
     * @return bool
     */
    public static function log($level,$message,array $context=[]){
        $data=[
            'level'=>$level,
            'message'=>$message,
            'context'=>$context,
            'channel'=>'AsyncLogger',
            'datetime'=>date('Y-m-d H:i:s'),
            'host'=>$_SERVER['SERVER_ADDR'] ?? '',
            'uri'=>$_SERVER['REQUEST_URI'] ?? '',
        ];

        $producer=Queue::getConnection('AsyncLogger',true);
        $producer->setExchangeOptions(['name'=>'async_logs','type'=>'topic','durable'=>true])->declareExchange();

        try{
            $producer->publish(json_encode($data),[
                'routing_key' =>'log',
                'exchange' =>'async_logs',
            ]);
            return true;
        }catch (Exception $e){
            return false;
        }
    }
}

日志记录器定义好后,使用队列发送日志记录信息,这里我们选择使用 RabbitMQ 当做队列服务。

// Consumer类
use BunnyMessage;
use PsrLogLoggerInterface;

class Consumer
{
    /**
     * @param Message $message
     * @param LoggerInterface $logger
     */
    public function process(Message $message,LoggerInterface $logger){
        $body=$message->content;
        $data= json_decode($body,true);
        $channel=$data['channel'] ?? 'default_logger';

        $logger->notice($data['message'], $data);
    }
}

其中,我们使用 appcommonQueue 类来提供 rabbitmq 的连接实例;data中除了记录日志的信息外,还包含一些环境信息,比如时间、IP地址、请求的uri地址等。

队列处理程序:

// Queue类
namespace appcommon;

use BunnyAsyncClient;
use BunnyChannel;
use BunnyMessage;
use BunnyProtocolMethodBasicConsumeOkFrame;
use BunnyProtocolMethodChannelCloseFrame;
use BunnyProtocolMethodChannelCloseOkFrame;
use BunnyProtocolMethodConnectionCloseFrame;
use BunnyProtocolMethodConnectionCloseOkFrame;
use BunnyProtocolMethodConnectionStartFrame;
use BunnyClientStateEnum;
use BunnyMessage as BunnyMessage;

class Queue
{
    /**
     * @param string $queueName
     * @return Client|null
     */
    public static function getConnection(string $routingKey, bool $persistent=false):?Client
    {
        $config=config('rabbitmq.async_log');
        $client=new Client([
            'host' => $config['host'],
            'port' => $config['port'],
            'user' => $config['user'],
            'password' => $config['password'],
            'vhost' => $config['vhost'],//注意此处改为需要的 VHOST
            'concurrency' => 2,
        ]);

        try{
            $client->connect();
            $client->channel()
                ->then(function (Channel $channel) use($client,$routingKey,$persistent){
                    $channel->exchangeDeclare('async_logs','topic',true,true);
                    $channel->queueDeclare($routingKey, $passive=false,$durable=true,$exclusive=false,$autoDelete=false,$nowait=false);
                    $channel->queueBind($routingKey, 'async_logs', $routingKey);

                    $channel->consume(
                        function ($msg, Channel $channel, BunnyMessage $message) use($client,$routingKey){
                            $className=config('rabbitmq.async_log.consumer');
                            $consumer=new $className($client,$routingKey);
                            $consumer->process($message,app('log.async_logger'));
                            $channel->ack($msg);//处理消息
                        },
                        $routingKey,//队列Name
                        '',//消费Tag
                        false,//no_local
                        false,//no_ack
                        false,//exclusive
                        $persistent ? ['delivery_mode'=>2] : []
                    );
                });
        }catch (Exception $e){
            return null;
        }finally{
            return $client;
        }
    }
}

当然,我们还需要一个辅助处理日志的类。

rrreee

上面这段代码中定义了队列连接的 host、port 等,通过 $client->channel() 创建了一个 channel 对象,通过 $channel->exchangeDeclare()$channel->queueDeclare() 创建了 exchange 和 queue,并将它们进行了绑定。最后,使用 $channel->consume()rrreee

Nachdem der Logger definiert wurde, verwenden Sie eine Warteschlange zum Senden von Protokollierungsinformationen. Hier verwenden wir RabbitMQ als Warteschlangendienst.

rrreee

Unter anderem verwenden wir die Klasse appcommonQueue, um Rabbitmq-Verbindungsinstanzen bereitzustellen. Zusätzlich zur Aufzeichnung von Protokollinformationen enthält data auch einige Umgebungsinformationen wie Zeit und IP Adresse, angeforderte URI-Adresse usw.

Warteschlangenhandler:
    rrreee
  1. Natürlich brauchen wir auch eine Klasse, die uns bei der Protokollverarbeitung unterstützt.
  2. rrreee
  3. Der obige Code definiert den Host, den Port usw. der Warteschlangenverbindung. Ein Kanalobjekt wird über $client->channel() erstellt, und ein Kanalobjekt wird über $channel->exchangeDeclare () und $channel->queueDeclare() erstellen Exchange und Warteschlange und binden sie. Verwenden Sie abschließend $channel->consume(), um Nachrichten aus der Warteschlange asynchron zu konsumieren und an die Nachrichtenverarbeitungsklasse zu senden.
  4. 3. Zusammenfassung
In diesem Artikel wird erläutert, wie Sie mit dem ThinkPHP6-Framework asynchrone Protokollierungsvorgänge durchführen, sodass die Protokollierung die Reaktionsgeschwindigkeit der Anwendung nicht mehr beeinträchtigt. Im Allgemeinen sind die folgenden Schritte:

🎜Entwickeln Sie Ihren eigenen asynchronen Logger. 🎜🎜Verwenden Sie RabbitMQ für die Nachrichtenwarteschlangenverarbeitung. 🎜🎜Schreiben Sie einen Nachrichtenhandler. 🎜🎜🎜In tatsächlichen Projekten müssen wir den Code entsprechend den spezifischen Anforderungen optimieren und anpassen die Konfiguration der Warteschlange. Durch asynchrone Protokollierung kann die Betriebseffizienz von Webanwendungen effektiv verbessert und die Stabilität und Zuverlässigkeit des Systems verbessert werden. 🎜

Das obige ist der detaillierte Inhalt vonWie verwende ich ThinkPHP6 für asynchrone Protokollierungsvorgänge?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn