Message queuing and order delay processing

Message queue
rabbimq introduction and installation
Extended installation
rabbimq is used in laravel
Message queue synchronization Redis products

  1. rabbitmq introduction and installation
    1.1 software introduction
    Message refers to the data transmitted between applications. Messages can be very simple, such as containing only text strings, or they can be more complex and may contain embedded objects.
    Message Queue is a communication mode between applications. Messages can be returned immediately after being sent. The message system ensures the reliable delivery of messages. The message publisher only publishes the message to MQ, regardless of who gets it. The message consumer only gets the message from MQ, regardless of who publishes it. In this way, publishers and users do not need to know each other's existence.
    RabbitMQ is an open source, complete and reusable enterprise message system written in erlang language based on AMQP. Support multiple languages, including java, Python, ruby, PHP, C/C + +.
    The core concept of RabbitMQ:
    Producer: an application that sends messages.
    Consumer: the application that receives the message.
    Queue: a cache that stores messages.
    Message: the information sent by the producer to the consumer through RabbitMQ.
    Connection: a TCP connection between RabbitMQ and the application server.
    Channel: a virtual channel in a connection. When you send or receive messages through the message queue, this operation is carried out through the channel.
    Exchange: the exchange is responsible for receiving messages from the producer and distributing them to the corresponding message queue according to the exchange type. To receive messages, a queue must be bound to a switch.
    Binding: binding is an associated connection between a queue and a switch.
    Routing Key: a Routing Key is a key for the switch to view and decide how to distribute messages to the queue according to the key. The Routing Key can be said to be the destination address of the message.
    Operating mode of RabbitMQ:
    Simple queue
    Work queue
    Publish subscribe mode
    Routing mode
    Theme mode
    1.2 rabbitmq installation
    1.Docker pulls rabbitmq image
    docker pull rabbitmq

Building rabbitmq container

docker run -p 5672:5672 -p 15672:15672 -d --name rabbitmq -v /docker/rabbitmq:/var/lib/rabbitmq --privileged=true --hostname myRabbitmq -e RABBITMQ_DEFAULT_VHOST=my_vhost -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin rabbitmq

Enter rabbitmq container installation visualization interface: rabbitmq_management
rabbitmq-plugins enable rabbitmq_management

Check whether the firewall is closed and whether the server security group port is open
Visit youhost:15672 to see the login interface of rabbitmq visualization tool. Just log in with the account and password set above.
2. Expansion installation

rabbitmq-c Dependence and amqp Extended installation
rabbitmq-c Dependent installation
tar zxf rabbitmq-c-0.8.0.tar.gz
cd rabbitmq-c-0.8.0
./configure --prefix=/usr/local/rabbitmq-c
 make install


First enter the php container to install the amqp extension. Here, use the source code to compile and install the amqp extension - > prepare the extension package - > enter the installation directory
Download address https://pecl.php.net/package/amqp

cd /home/amqp-1.10.2

find / -name phpize

#Generate phpize installation files
/usr/local/bin/phpize

#Check whether the PHP config file path is consistent with -- with PHP config = / usr / local / bin / PHP config
find / -name php-config

./configure --with-php-config=/usr/local/bin/php-config --with-amqp --with-librabbitmq-dir=/usr/local/rabbitmq-c
 
 make install

Possible problems: amqp_ssl_socket.h cannot be found. Go to the libbitmq installation package directory and copy CP / home / rabbitmq-c-0.8.0/libbitmq/amqp_ssl_socket.h /home/amqp-1.10.2/
Add in php.ini

extension=amqp.so

  1. rabbimq is used in laravel
    Installation components
    composer require vladimir-yuldashev/laravel-queue-rabbitmq "10.X" --ignore-platform-reqs
    Add laravel configuration for rabbitmq
    Configuration of rabbitmq in queue.php
'rabbitmq' => [
            'driver' => 'rabbitmq',
            'queue' => env('RABBITMQ_QUEUE', 'default'),
            'connection' => PhpAmqpLib\Connection\AMQPLazyConnection::class,

            'hosts' => [
                [
                    'host' => env('RABBITMQ_HOST', '127.0.0.1'),
                    'port' => env('RABBITMQ_PORT', 5672),
                    'user' => env('RABBITMQ_USER', 'guest'),
                    'password' => env('RABBITMQ_PASSWORD', 'guest'),
                    'vhost' => env('RABBITMQ_VHOST', '/'),
                ],
            ],

            'options' => [
                'ssl_options' => [
                    'cafile' => env('RABBITMQ_SSL_CAFILE', null),
                    'local_cert' => env('RABBITMQ_SSL_LOCALCERT', null),
                    'local_key' => env('RABBITMQ_SSL_LOCALKEY', null),
                    'verify_peer' => env('RABBITMQ_SSL_VERIFY_PEER', true),
                    'passphrase' => env('RABBITMQ_SSL_PASSPHRASE', null),
                ],
                'queue' => [
                    'job' => \VladimirYuldashev\LaravelQueueRabbitMQ\Queue\Jobs\RabbitMQJob::class,
                ]
            ],

            /*
             * Set to "horizon" if you wish to use Laravel Horizon.
             */
            'worker' => env('RABBITMQ_WORKER', 'default'),
        ]

In the. env file

rabbitmq queue is used by default

QUEUE_CONNECTION=rabbitmq

Queue driver used

QUEUE_DRIVER=rabbitmq

ip address of mq

RABBITMQ_ Port with host = 172.17.0.10 # MQ
RABBITMQ_ Account number of port = 5672 # MQ
RABBITMQ_ Password for user = admin # MQ
RABBITMQ_PASSWORD=admin

Default virtual host

RABBITMQ_VHOST=my_vhost

Default queue name

RABBITMQ_QUEUE=lmrs

  1. Message queue synchronization Redis products
    Complete consumption through rabbitmq message queue, and modify the data in redis after consumption
    Code in ProductController.php
<?php
//... omit some code
class ProductController extends Controller
{

//... omit some code

    public function update(Request $request)
    {
        //Get product information
        $product = Product::find($request->input("id"));
        $product->update([
            "name" => $request->input("name"),
            "long_name" => $request->input("long_name")
        ]);
//        return Product::find($request->input("id"));
        if ($product){
            //Instantiate job
            $this->dispatch(new UpdateProduct(Product::find($request->input("id"))));
            return "success";
        }
        return "Failed";
    }

}
?>

Code in UpdateProduct.php

<?php
namespace App\Jobs;

use App\Services\RateLimitService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Services\RabbitmqService;

class UpdateProduct implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    protected  $productKey;
    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($data)
    {
        $this->productKey = "Lmrs::product::info::".$data->id;
        //Write queue
        RabbitmqService::push('update_queue',$data);
    }
    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
     //Take out consumption
        RabbitmqService::pop('update_queue',function ($message){

        //Update redis
            $product = app('redis')->set($this->productKey,serialize($message));
            if (!$product){
                return;
            }
            print_r($message);
            return true;
        });
    }
    //exception handling
    public function failed(\Exception $exception)
    {
        print_r($exception->getMessage());
    }
}
?>

Prepare the Rabbitmq service class. The code in RabbitmqService.php is as follows

<?php

namespace App\Services;

use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;

class RabbitmqService
{
    public static function getConnect()
    {
        //RABBITMQ configuration item
         $config = [
            'host' => env('RABBITMQ_HOST', '127.0.0.1'),
            'port' => env('RABBITMQ_PORT', 5672),
            'user' => env('RABBITMQ_USER', 'guest'),
            'password' => env('RABBITMQ_PASSWORD', 'guest'),
            'vhost' => env('RABBITMQ_VHOST', '/'),
        ];

        return new AMQPStreamConnection($config["host"],$config["port"],$config["user"],$config["password"],$config["vhost"]);
    }
    //producer
    public static function push($queue,$messageBody,$exchange='router')
    {
        //Get connection
        $connection = self::getConnect();
        //Build channel
        $channel = $connection->channel();
        //Declare a queue
        $channel->queue_declare($queue,false,true,false,false);
        //Specifies that the switch is in routing mode
        $channel->exchange_declare($exchange,'direct',false,true,false);
        //Bind queue and type
        $channel->queue_bind($queue,$exchange);
        $message = new  AMQPMessage($messageBody,array('content_type' => 'text/plain', 'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT));
        //Message push
        $channel->basic_publish($message,$exchange);
        $channel->close();
        $connection->close();
    }
    //Consumer: take out the message for consumption and return it
    public static function pop($queue,$callback,$exchange='router')
    {
        $connection = self::getConnect();
        $channel = $connection->channel();
        //Remove message from queue
        $message = $channel->basic_get($queue);
        $res = $callback($message->getBody());
        if ($res){
            //ack verification
            $channel->basic_ack($message->getDeliveryTag());
        }
        $channel->close();
        $connection->close();
    }
}
?>

If redis synchronization fails, delete the queue and try again

Posted by XeNoMoRpH1030 on Thu, 04 Nov 2021 22:37:38 -0700