Suggestions on the use of RabbitMQ

Posted by Master Zen on Wed, 29 Dec 2021 12:11:57 +0100

 After more than 4 years of use experience, Found that there are many misunderstandings and wrong codes on the Internet. In order to clarify some wrong ideas and ways of use.  I specially wrote this article to unify everyone's programming standards and naming standards, Facilitate system development and system integration.

Added some common questions and guidelines in other articles And naming Guide

First establish a code connection, then bind, and then send

Is the connection with RabbitMQ in the code good to keep a long connection open for permanent use? Or open it every time you need it?

During database operation, it is recommended to open the connection and then close it every time the query is executed
Should this be the case when operating RabbitMQ?

My suggestions are as follows: excerpt from https://www.javaroad.cn/questions/94679

In RabbitMQ, connections are considered "expensive" - they occupy TCP / IP ports, require handshake / negotiation, and so on Although this seems insignificant in the field of SQL Server, this overhead becomes infeasible when you talk about sending 100K messages per second in RabbitMQ

Therefore, for RabbitMQ, the general best practice is to open a connection for each application instance and keep it open for as long as possible - if possible, it is better to have the same life cycle as the application instance. I personally generally set it to static

In the app instance, you can create Channels on the RabbitMQ connection You can create them very quickly Most applications use a single channel for a single operation in rabbit MQ Message producer? Open a channel Consume from queue? Open a channel Redefine queue? Open Channels, etc

Also - if you use a language with threads, such as C, you must limit your Channels to one thread Do not reuse Channels across threads If you try to do this, something very bad will happen

So according to the above guidelines, my news producer publishes the news code

   static Connection connection = null; 
   static Object lock = new Object();
   
    public boolean NoticeAI(String msg) throws IOException, TimeoutException{ 
      // SocketServe.SendToClients(msg); 
    //   String queneName = "firstQueue";
      String exchangeName = appconfig.getAppRabbitMQExchangeName();
    //   String routingKey = "test1";
      Channel channel = null;
      try {
          
          synchronized(lock)
          { 
                if (connection == null)
                { 
                    ConnectionFactory factory = new ConnectionFactory();
                    factory.setHost(appconfig.getAppRabbitMQIP());
                    factory.setPort(appconfig.getAppRabbitMQPort());
                    factory.setUsername(appconfig.getAppRabbitMQUserName());
                    factory.setPassword(appconfig.getAppRabbitMQPassword());
                    factory.setVirtualHost(appconfig.getAppRabbitMQVirtualHost());
                    // Create a TCP connection to the RabbitMQ server
                    connection = factory.newConnection();
                }
          }
          
          // Create a channel,
          channel = connection.createChannel();
/*** I see a lot of people define queues here and define the binding between queues and switches. In fact, this is unreasonable The code is as follows, which has been commented*/
            // Declare the default queue (or use the default queue without declaring the queue)
            //channel.queueDeclare(queneName, true, false, true, null);
            // String queue = channel.queueDeclare().getQueue();
            // Bind queue to switch
            //channel.queueBind(queneName, exchangeName, routingKey);
/** Unreasonable code end   */
          channel.exchangeDeclare(exchangeName, "topic", true); 
          channel.basicPublish(exchangeName, "Event.WebAPI.DataReceived", null, msg.getBytes()); 
          return  true;
      } catch (Exception ex) {
          ex.printStackTrace(); 
          return  false;
      } finally {
          if (channel != null) {
              channel.close();
          }
      }
    }
 

    protected void finalize( )
    {
        if (connection != null)
        {
            try {
                connection.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } 
    }

About the naming rules of RoutingKey My suggestion is

E. System event

For example:

E.WebAPI.DataReceived / / means that the webapi system triggers the event that data has been received
E.WebAPI.OrderIsCreate / / means that the webapi system triggers the event that the order has been created
E.WebAPI.OrderIsDelete / / the webapi system triggers the event that the order has been deleted
E.WebAPI.OrderIsCheck / / means that the webapi system triggers the event that the order has been approved
E.WebAPI.OrderIsInStock / / the webapi system triggers the event that the order has been received

In my concept, RoutingKey is approximately equal to the event name This event name must be able to distinguish between systems and business operations
The bigger the concept, the more to the left It is easy to be uniformly subscribed by topic mode For example, if I want to subscribe to all business logs of the web API, I can subscribe to events when the queue is bound WebAPI.*

About the naming rules of QuneName My suggestion

Q. System method. on. System event

Q.ERP.CreateWorkOrder.on.WebAPI.OrderIsCheck
It means that when the WebAPI data has been received, the ERP system starts to create a production work order

Q.ERP.CancelWorkOrder.on.WebAPI.OrderIsDelete
It means that the WebAPI system is triggered and the ERP system begins to cancel the production work order

Q.ERP.CompleteWorkOrder.on.WebAPI.OrderIsInStock
It means that the WebAPI system triggers the event that the order has been received, and the ERP system modifies the work order to the completed status

Topics: RabbitMQ Distribution