Application of RabbitMQ in practical projects

Posted by poe on Thu, 17 Feb 2022 14:48:24 +0100

Application of RabbitMQ in practical projects

Business scenario

explain:

For some reasons, the specific business is not explained. The general business scenario is that module A will send A message to module B, and module B will update the local cache encache And module B is A cluster deployment in the project.

Switch selection:

1. fanout will route messages on all switches to all queues bound with the switch, and BindingKey is not required to take effect

2. direct: it routes the message to a queue whose BindingKey exactly matches the RoutingKey.

3. topic: it is an extension of direct. It also uses RoutingKey and BindingKey to match, but the matching rules are different. It supports fuzzy matching. There are the following rules

      • RoutingKey is a dot "." Separated string, each separated independent string is a word, which is the matching unit;
      • BindingKey, like RoutingKey, is also "." Split string;
      • But the difference is that BindingKey can use "#" and "" for fuzzy matching similar to placeholders, "#" represents one word and "" represents multiple words (or zero)

4. Headers: match by relying on the headers attribute in the sending message content. Specify a set of key value pairs when binding the queue and the switch. Here is headers. When sending a message to the switch, RabbitMQ will get the headers of the message and route it to the relevant queue through comparison. This switch has poor performance and is generally not used.

The above is the switch type. According to this scenario, we will generally consider using fanout (or direct)

See the figure below for details:

Illustration

realization

It is explained here that spring boot integrates rabbitmq and uses the direct model switch to realize the business scenario and show the code of consumers

pom.xml add dependency

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
 </dependency>

application.proerties adding switch and routing configurations

rabbitmq.admin.exchange=admin.billinfo
rabbitmq.admin.routingkey=admin.billinfo

Add RabbitmqConfig class

@Configuration
public class RabbitMqConfig {
	private  final Logger logger = LoggerFactory.getLogger(RabbitMqConfig.class);

	
    @Value("${rabbitmq.admin.exchange}")
    String  adminExchange;

    @Value("${rabbitmq.admin.routingkey}")
    String  adminRouteKey;
	 
	 @Value("${stationno}")
	 public  Integer stationno;//Site number
    //Queue naming and switch naming
    @Bean
    public Queue AdminQueue() {
        return new Queue("admin.billinfo"+station,true);  //Whether true is persistent
    }
    @Bean
    DirectExchange AdminQueueExchange() {
        return new DirectExchange(adminExchange==null?"admin.billinfo":adminExchange.trim());
    }
    //Switch and queue binding
    @Bean
    Binding bangdingDirect() {
        return BindingBuilder.bind(AdminQueue()).to(AdminQueueExchange()).with(adminRouteKey==null?"":adminRouteKey.trim());
    }

}

Message consumer

@Component
@RabbitListener(queues = "admin.billinfo")//Name of queue listening
public class CacheReceiver {
    private  final Logger logger = LoggerFactory.getLogger(DirectReceiver.class);

    @Autowired
    PredictPoolMemory predictPoolMemory;
    @Autowired
    PreviewPoolMemory previewPoolMemory;
    @Autowired
    AgentPoolMemory agentPoolMemory;

    @Autowired
    PredictNumberPoolDao predictNumberPoolDao;
    @Autowired
    PreviewNumberPoolDao previewNumberPoolDao;
    @Autowired
    AgentNumberPoolDao agentNumberPoolDao;
    @Autowired
    JobCache jobCache;



    //Received message
    @RabbitHandler
    public void process(String billInfoMessage){
        logger.info("adminbillinfo:{}",billInfoMessage);
        JSONObject jsonobj = JSON.parseObject(billInfoMessage);
        String cmd = jsonobj.getString("cmd");
        int type = jsonobj.getIntValue("type");
        int companyid  = jsonobj.getIntValue("companyid");

        //Modify enterprise information
        if ("updatecompanyinfo".equals(cmd)){
            try {
                predictPoolMemory.addAll();
            } catch (Exception e) {
                logger.error("Exception:{}"+e.getMessage(),e);
            }

            try {
                previewPoolMemory.addAll();
            } catch (Exception e) {
                logger.error("Exception:{}"+e.getMessage(),e);
            }

            try {
                agentPoolMemory.addAll();
            } catch (Exception e) {
                logger.error("Exception:{}"+e.getMessage(),e);
            }
            try{
                jobCache.initCache();
            }catch (Exception e){
                logger.error("Exception{}"+e.getMessage(),e);
            }
        }
}

Solution to the problem of message backlog in online mq

The mq automatic confirmation mode acknowledge = auto, without exception handling, will cause mq consumers to consume abnormally, and the messages will return to the queue, resulting in message backlog

Configuration can be added

# Enable ACK no confirmation mode
spring.rabbitmq.listener.direct.acknowledge-mode=none
spring.rabbitmq.listener.simple.acknowledge-mode=none

In addition to NONE and MANUAL, the acknowledge mode also has AUTO. It will decide whether to confirm or reject (whether to re-enter the queue) according to the execution of the method

  • If the message is successfully consumed (success means that no exception is thrown in the process of consumption), it is automatically confirmed

  • When the AmqpRejectAndDontRequeueException exception is thrown, the message will be rejected and request = false (do not re-enter the queue)

  • When the ImmediateAcknowledgeAmqpException exception is thrown, the consumer will be confirmed

  • For other exceptions, the message will be rejected and request = true (if only one consumer listens to the queue at this time, there is a risk of life and death cycle, and multiple consumers will also cause a great waste of resources, which must be avoided in the development process). You can set it through setDefaultRequeueRejected (the default is true)

Detailed online mq troubleshooting, please pay attention to official account: gentlemen and hooligans.

Topics: Java RabbitMQ Spring queue switch