How to improve the reliability of RabbitMQ message consumption in human resource management system

Keywords: RabbitMQ Spring Redis Database

Learn how to improve the reliability of RabbitMQ message consumption in human resource management system, and avoid repeated consumption of messages.

1 General

stay How to improve the reliability of RabbitMQ message sending in human resource management system In this paper, we ensure the reliability of message sending. However, under such a mechanism, new problems arise, that is, messages may be delivered repeatedly, which leads to repeated consumption of messages. For example, when an employee enters the company, he / she receives two welcome emails. We need to deal with this problem through technical means. For example, adding message consumption confirmation mechanism can effectively improve the reliability of message consumption.

When it comes to this topic, we have to talk about message idempotence first.

2 idempotent

Idempotence itself is a mathematical concept, even if the formula: F (x) = f (x)) can be established. In the development field, it means that for the same system, using the same conditions, one request and multiple requests have the same impact on system resources.

In the distributed system, idempotence is particularly important, because in the distributed system, we often use the function of interface call failure and retry, which brings about repeated calls to an interface under the same conditions. In this case, it is particularly important to ensure the idempotence of the interface. Common solutions are:

  • MVCC mechanism: MVCC multi version concurrency control. This method is to compare the version number of the data held during data update. If the version number is inconsistent, the operation will fail. In this way, each version has only one chance of success. Once it fails, it must be retrieved again.
  • Token mechanism: token is a widely used method at present. The core idea is that each operation has a unique credential token. Once executed successfully, the same result will always be returned for repeated requests.
  • Design of the counterweight
  • ...

The consumer end of RabbitMQ in human resource management system actually uses Token.

3 Token mechanism

The general idea is as follows: first, change the message automatic confirmation mechanism of RabbitMQ to manual confirmation, and then record the unique ID of a message on Redis every time a message is consumed successfully, and then check whether there is a message on Redis every time a message is received ID, if any, indicates that the message has been consumed and will not be processed, otherwise, it will be processed again.

First, modify the pom file in HR mail to increase Redis dependency, as follows:

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

Next, modify the application.properties file, add Redis configuration, modify RabbitMQ configuration, and open message consumption for manual confirmation, as follows:

# Configure RabbitMQ
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
## Enable message consumption manual confirmation, default automatic
spring.rabbitmq.listener.simple.acknowledge-mode=manual
spring.rabbitmq.listener.simple.prefetch=100

# Configure Redis to realize idempotence of RabbitMQ message consumption and avoid repeated message consumption. See RabbitMQReceiver
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.database=0
spring.redis.password=

Finally, modify the message consumption method in RabbitMQReceiver and add the message consumption confirmation mechanism as follows:

// listen queue 
@RabbitListener(queues = MailConstants.QUEUE_NAME)
public void employeeWelcome(Message message, Channel channel) throws IOException {
    Employee employee = (Employee) message.getPayload();
    MessageHeaders headers = message.getHeaders();
    Long tag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
    String msgId = (String) headers.get("spring_returned_message_correlation");
    if (stringRedisTemplate.opsForHash().entries("mail_log").containsKey(msgId)) {
        // redis contains the key, indicating that the message has been consumed
        logger.info("Message has been consumed:" + msgId);
        channel.basicAck(tag, false); // Manual confirmation message consumed
        return;
    }
    logger.info(employee.toString());

    // Send mail
    MimeMessage msg = javaMailSender.createMimeMessage();
    MimeMessageHelper helper = new MimeMessageHelper(msg);
    try {
        helper.setSubject("Entry notice");
        helper.setFrom(mailProperties.getUsername());
        helper.setTo(employee.getEmail());
        helper.setSentDate(new Date());

        Context context = new Context();
        context.setVariable("name", employee.getName());
        context.setVariable("positionName", employee.getPosition().getName());
        context.setVariable("jobTitlelName", employee.getJobTitle().getName());
        context.setVariable("departmentName", employee.getDepartment().getName());
        String process = templateEngine.process("employee/welcome", context);
        helper.setText(process, true);
        javaMailSender.send(msg);

        stringRedisTemplate.opsForHash().put("mail_log", msgId, "cxy35");
        channel.basicAck(tag, false); // Manual confirmation message consumed
        logger.info("Message sent successfully:" + msgId);
    } catch (MessagingException e) {
        channel.basicNack(tag, false, true); // Message consumption failed, return to queue
        e.printStackTrace();
        logger.error("Failed to send message:" + e.getMessage());
    }
}

Scan code concerns WeChat programmer 35, gets the latest technology dry cargo, chatting programmers 35, 35 programmers official account. Independent site: https://cxy35.com

Posted by ijug.net on Sat, 09 May 2020 02:58:55 -0700