Rumah  >  Artikel  >  rangka kerja php  >  Bagaimana untuk menggunakan ThinkPHP6 untuk operasi pembalakan tak segerak?

Bagaimana untuk menggunakan ThinkPHP6 untuk operasi pembalakan tak segerak?

WBOY
WBOYasal
2023-06-12 09:57:112157semak imbas

Dengan perkembangan pesat Internet, perkhidmatan pembalakan telah menjadi modul penting untuk setiap aplikasi web berskala besar. Untuk memudahkan pelbagai keperluan seperti penyelesaian masalah ralat dan pemantauan prestasi, artikel ini akan memperkenalkan cara menggunakan rangka kerja ThinkPHP6 untuk melaksanakan operasi pengelogan tak segerak.

1. Apakah itu pembalakan

Dalam bidang sains komputer, pembalakan merujuk kepada rakaman peristiwa dan maklumat yang berlaku dalam sistem komputer. Biasanya, rekod ini disimpan dalam fail atau pangkalan data. Pembalakan membantu memahami status pengendalian sistem, menemui dan menyelesaikan masalah tepat pada masanya, dan dengan itu meningkatkan kebolehpercayaan dan kestabilan sistem.

Dalam aplikasi web, pengelogan boleh membantu pembangun lebih memahami masalah dan ralat yang dihadapi oleh sistem. Berdasarkan pengelogan, pembangun dapat memahami dengan jelas tingkah laku aplikasi dan di mana dan bila ralat berlaku.

2. Pengelogan tak segerak ThinkPHP6

Dalam proses pembangunan aplikasi, pengelogan ialah modul penting. Selain itu, pengelogan selalunya merupakan operasi yang memakan masa yang boleh menjejaskan prestasi sistem jika dilakukan secara serentak. Untuk tujuan ini, ThinkPHP6 memperkenalkan fungsi pengelogan tak segerak, supaya pengelogan tidak lagi menjejaskan kelajuan tindak balas aplikasi.

Biasanya log masuk pengawal atau model, kami menggunakan antara muka PsrLogLoggerInterface yang disuntik untuk mencapainya.

// Controller或Model中
use PsrLogLoggerInterface;

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

Mudah digunakan. Untuk menggunakan pengelogan tak segerak, takrifkan pengelog tak segerak:

use MonologLogger;
use MonologHandlerStreamHandler;

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

Selepas pengelog ditakrifkan, gunakan baris gilir untuk menghantar maklumat pengelogan Di sini kami memilih untuk menggunakan RabbitMQ sebagai perkhidmatan baris gilir.

// 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;
        }
    }
}

Antaranya, kami menggunakan kelas appcommonQueue untuk menyediakan contoh sambungan rabbitmq selain merekod maklumat log, data juga mengandungi beberapa maklumat persekitaran, seperti masa, alamat IP, alamat uri yang diminta; , dsb.

Pengendali baris gilir:

// 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);
    }
}

Sudah tentu, kami juga memerlukan kelas untuk membantu dalam memproses log.

// 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;
        }
    }
}

Kod di atas mentakrifkan hos, port, dll. sambungan baris gilir, mencipta objek saluran melalui $client->channel(), mencipta pertukaran dan baris gilir melalui $channel->exchangeDeclare() dan $channel->queueDeclare(), serta menghubungkannya Mengikat . Akhir sekali, gunakan $channel->consume() untuk menggunakan mesej daripada baris gilir secara tidak segerak dan menghantar mesej ke kelas pemprosesan mesej.

3. Ringkasan

Artikel ini memperkenalkan cara menggunakan rangka kerja ThinkPHP6 untuk melaksanakan operasi pengelogan tak segerak supaya pengelogan tidak lagi menjejaskan kelajuan tindak balas aplikasi. Secara keseluruhannya, berikut ialah langkah-langkahnya:

  1. Bangunkan pembalak tak segerak anda sendiri
  2. Gunakan RabbitMQ untuk pemprosesan baris gilir mesej
  3. Tulis pengendali mesej

Dalam projek sebenar, kami perlu mengoptimumkan kod dan melaraskan konfigurasi baris gilir mengikut keperluan khusus. Melalui pengelogan tak segerak, kecekapan pengendalian aplikasi web boleh dipertingkatkan dengan berkesan, dan kestabilan dan kebolehpercayaan sistem boleh dipertingkatkan.

Atas ialah kandungan terperinci Bagaimana untuk menggunakan ThinkPHP6 untuk operasi pembalakan tak segerak?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn