RabbitMQ getting started-publish/subscribe, and rabbitmq getting started

Source: Internet
Author: User
Tags amq

RabbitMQ getting started-publish/subscribe, and rabbitmq getting started

What is publishing and subscription?

Publishing and subscription is a design mode that defines one-to-many dependencies so that multiple subscriber objects can listen to a topic object at the same time. When the status of this topic object changes, it notifies all subscriber objects so that they can automatically update their status.

To describe this mode, we will build a simple log system. It includes two programs: the first program is responsible for sending log messages, and the second program is responsible for obtaining messages and outputting content. In our log system, all running receiver programs accept messages. We use one receiver to write logs to the hard disk, and the other receiver to output the logs to the screen. Eventually, the log message is broadcast to all recipients (receivers ).

Exchanges

The core idea of the RabbitMQ message model is that the producer will never directly send any messages to the queue, and the producer can only send messages to the exchange. exchange is relatively simple and receives messages from the producer, push messages to the queue. Exchange must clearly know the rules to which messages should be routed to the corresponding queue, and the specific routing algorithm used is determined by the exchange type. The AMQP protocol provides four types of switches:

Name (vswitch type)

Default pre-declared names (pre-declared Default name)

Direct exchange (Direct Connect switch)

(Empty string) and amq. direct

Fanout exchange (fan type switch)

Amq. fanout

Topic exchange (Topic switch)

Amq. topic

Headers exchange (Head switch)

Amq. match (and amq. headers in RabbitMQ)

In addition to the vswitch type, the vswitch can also be declared with many other attributes, the most important of which are:

  • Name
  • Durability)
  • Auto-delete (when all the message queues bound to this switch are used, delete it)
  • Arguments (dependent on the proxy itself)

    A vswitch can have two statuses: durable and transient ). Persistent switches will still exist after the broker is restarted, while temporary switches will not (they need to be declared again after the proxy is launched again ). However, not all application scenarios require persistent switches.

    The following two types of switches are described in this article: directly connected switch (the switch type used in the previous examples) and slice switch (the switch type to be used in this article)

    Direct Connect Switch

    Direct exchange can use the routing key carried by messages to deliver messages to the corresponding queue. The unicast route (unicast routing) used to process messages. It can also process multicast routes.

    How does it work?

    • Bind a queue to a vswitch and specify a route key for the binding)
    • When a message carrying a route key of R is sent to a directly connected switch, the switch routes it to a queue with the same bound value of R.

    Directly Connected switches are often used to distribute tasks cyclically to multiple workers. When doing so, you must understand that the load balancing of messages occurs between consumers, instead of queue.

    Example of a directly connected vswitch:

    Slice Switch

    A fan-sector switch (funout exchange) routes messages to all queues bound to it, regardless of the bound route key (routing key ). The Slice switch is used to process the broadcast routing (broadcast routing) of messages ).

    Slice switches are suitable for the following scenarios because they ship messages to all queues bound to them:

    • Large-scale multi-user online (MMO) games can be used to handle global events such as ranking updates.
    • Sports News websites can use it to distribute score updates to mobile clients in near real time.
    • The distribution system uses it to broadcast various statuses and Configuration updates.
    • In group chat, it is used to distribute messages to users involved in group chat. (AMQP does not have the built-in presence concept, so XMPP may be a better choice)

    Sector switch legend

    Create exchange

     

    Channel. ExchangeDeclare (exchange: "log_exchange", // exchange name

    Type: ExchangeType. Fanout, // exchange type

    Durable: false,

    AutoDelete: false,

    Arguments: null );

     

    Temporary queue

    In the previous examples, we have specified a name for each famous queue, because we want the consumer to point to the correct queue. When we want to share a queue between producers and consumers, it is very important to name the queue.

    However, the log system we want to implement only wants to get all the messages, and is only interested in the messages currently being transmitted, and does not care about the queue name. To meet our needs, there are two things to do:

    No matter when we connect to RabbitMQ, we need a new empty queue. To achieve this goal, we can use a random number to create a queue or let the server provide us with a random name.

    Once the consumer is disconnected from RabbitMQ, the queue accepted by the consumer should be deleted automatically.

    Create temporary queue

     

    // Create an unnamed new message queue,

    QueueDeclareOk queue = channel. QueueDeclare (queue: "", // queue name, which is automatically assigned when it is null

    Durable: false,

    Exclusive: false,

    AutoDelete: true, // automatic deletion. If the queue does not have any subscribed consumers, the queue will be automatically deleted. This type of queue applies to temporary queues.

    Arguments: null );

    // Or

    // Queue = channel. QueueDeclare ();

     

    Bind

    We have created a fan-type switch (fanout) and a queue. Now we need to tell the switch how to send messages to our queue. The connection between the switch and the queue is called binding)

    Relationship between creating a vswitch and a queue

     

    // The fan-sector switch (funout exchange) routes messages to all queues bound to it, regardless of the bound routing key)

    // Fanout exchange does not need to specify the routing key.

    // Notify exchange of the message queues to which messages are sent by binding.

    Channel. QueueBind (queue: queueName, exchange: EXCHANGE_NAME, routingKey: ROUTING_KEY, arguments: null );

     

    Complete code:

    Producer Pub_SubProducer.cs

     

    Using System;

    Using System. Collections. Generic;

    Using System. Linq;

    Using System. Text;

    Using System. Threading. Tasks;

    Using RabbitMQ. Client;

     

    Namespace RabbitMQProducer

    {

    Public class Pub_SubProducer

    {

    Const string EXCHANGE_NAME = "log_exchange ";

    Const string ROUTING_KEY = "";

     

    // Send messages directly to the vswitch

    Public static void Publish ()

    {

    Var factory = new ConnectionFactory ()

    {

    HostName = "127.0.0.1"

    };

    Using (var connection = factory. CreateConnection ())

    {

    Using (IModel channel = connection. CreateModel ())

    {

    Channel. ExchangeDeclare (exchange: EXCHANGE_NAME, // exchange name

    Type: ExchangeType. Fanout, // exchange type

    Durable: false,

    AutoDelete: false,

    Arguments: null );

     

    Parallel. For (1,100, item =>

    {

    String message = $ "log Content {DateTime. Now. ToString ()}";

    Channel. BasicPublish (exchange: EXCHANGE_NAME, routingKey: ROUTING_KEY, basicProperties: null, body: Encoding. UTF8.GetBytes (message ));

    Console. WriteLine (message );

    });

     

    Console. WriteLine ("Press [enter] to exit .");

    Console. ReadLine ();

    }

    }

    }

    }

    }

     

    Consumer Pub_SubConsumer.cs

     

    Using RabbitMQ. Client;

    Using System;

    Using System. Collections. Generic;

    Using System. Linq;

    Using System. Text;

    Using System. Threading. Tasks;

    Using RabbitMQ. Client. Events;

    Using System. IO;

     

    Namespace RabbitMQConsumer

    {

    Public class Pub_SubConsumer

    {

    Const string EXCHANGE_NAME = "log_exchange ";

    Const string ROUTING_KEY = "";

    // Output to the screen

    Public static void Subscribe ()

    {

    Var factory = new ConnectionFactory ()

    {

    HostName = "127.0.0.1"

    };

    Using (var connection = factory. CreateConnection ())

    {

    Using (IModel channel = connection. CreateModel ())

    {

    Channel. ExchangeDeclare (exchange: EXCHANGE_NAME, // exchange name

    Type: ExchangeType. Fanout, // exchange type

    Durable: false,

    AutoDelete: false,

    Arguments: null );

     

    // Create an unnamed new message queue,

    QueueDeclareOk queue = channel. QueueDeclare (queue: "", // queue name, which is automatically assigned when it is null

    Durable: false,

    Exclusive: false,

    AutoDelete: true, // automatic deletion. If the queue does not have any subscribed consumers, the queue will be automatically deleted. This type of queue applies to temporary queues.

    Arguments: null );

    // Or

    // Queue = channel. QueueDeclare ();

     

    String queueName = queue. QueueName;

    // The fan-sector switch (funout exchange) routes messages to all queues bound to it, regardless of the bound routing key)

    // Fanout exchange does not need to specify the routing key.

    // Notify exchange of the message queues to which messages are sent by binding.

    Channel. QueueBind (queue: queueName, exchange: EXCHANGE_NAME, routingKey: ROUTING_KEY, arguments: null );

     

    EventingBasicConsumer consumer = new EventingBasicConsumer (channel );

    Consumer. Received + = (sender, args) =>

    {

    String message = Encoding. UTF8.GetString (args. Body );

    Console. WriteLine (message );

    };

     

    Channel. BasicConsume (queue: queueName, noAck: true, consumer: consumer );

     

    Console. WriteLine ("Press [enter] to exit .");

    Console. ReadLine ();

    }

    }

    }

     

    /// <Summary>

    /// Output to file

    /// </Summary>

    Public static void SubscribeFile ()

    {

    Var factory = new ConnectionFactory ()

    {

    HostName = "127.0.0.1"

    };

    Using (var connection = factory. CreateConnection ())

    {

    Using (IModel channel = connection. CreateModel ())

    {

    Channel. ExchangeDeclare (exchange: EXCHANGE_NAME, // exchange name

    Type: ExchangeType. Fanout, // exchange type

    Durable: false,

    AutoDelete: false,

    Arguments: null );

     

    // Create an unnamed new message queue,

    QueueDeclareOk queue = channel. QueueDeclare (queue: "", // queue name, which is automatically assigned when it is null

    Durable: false,

    Exclusive: false,

    AutoDelete: true, // automatic deletion. If the queue does not have any subscribed consumers, the queue will be automatically deleted. This type of queue applies to temporary queues.

    Arguments: null );

    // Or

    // Queue = channel. QueueDeclare ();

     

    String queueName = queue. QueueName;

    // The fan-sector switch (funout exchange) routes messages to all queues bound to it, regardless of the bound routing key)

    // Fanout exchange does not need to specify the routing key.

    // Notify exchange of the message queues to which messages are sent by binding.

    Channel. QueueBind (queue: queueName, exchange: EXCHANGE_NAME, routingKey: ROUTING_KEY, arguments: null );

     

    EventingBasicConsumer consumer = new EventingBasicConsumer (channel );

    Consumer. Received + = (sender, args) =>

    {

    String message = Encoding. UTF8.GetString (args. Body );

     

    // Write logs to the txt file

    Using (StreamWriter writer = new StreamWriter (@ "c: \ log \ log.txt", true, Encoding. UTF8 ))

    {

    Writer. WriteLine (message );

    Writer. Close ();

    }

     

    Console. WriteLine (message );

    };

     

    Channel. BasicConsume (queue: queueName, noAck: true, consumer: consumer );

     

    Console. WriteLine ("Press [enter] to exit .");

    Console. ReadLine ();

    }

    }

    }

    }

    }

     

    Run the above instance code to find that each subscriber instance can get the same content.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.