RabbitMQ implementation of distributed task scheduling based on delay

A. Distributed delay task

Traditional practice is to delay the task into the database, using the timing to scan, whether to match the task expires, and the set task is performed due to the completion status. This approach is also in a distributed environment require special handling (plus distributed lock) avoid the timing task is repeated for scanning.

However, the use RabbitMQ can achieve a natural delay task to solve the problem in distributed environments executed repeatedly (consumer will only be a consumer of this feature allows a delay task will be executed using the consumer mq message). Based on the core task delay RabbitMQ do it is to use the RabbitMQ message expiration forwarding feature. Set to send a message when the message expiration time, and so the message will expire when the message was not forwarded to the consumer a new queue, the queue of new customers receive the message and then processed using this delay time difference characteristics to achieve the task trigger .

II. RabbitMQ and set the delay to prepare the task used in the relevant queue

1. Install and erlang RabbitMQ (note erlang correspondence relationship with RabbitMQ version)

2. Openrabbitmq_management

Open RabbitMQ Command Prompt enter the command:rabbitmq-plugins enable rabbitmq_management

3. Create two Exchange

Create an Exchange add delay task, the following configuration

 

 Exchange then create a task for receiving the expiration of the delay, the following configuration

 

4. Create two Queue

Create the first Queue, for adding the delay task, the following configuration

 

The above configuration creates a queue q1, setting a destination Exchange expiration message is transferred (DLX) and Route key (dlx_rk)

Next, configure Exchange q1 bound to ExQ1, Route key to send

 

 

 Then create a second Queue, due to the receive queue q1 task is transferred, the following configuration

 

And bind to the Exchange: dlx, Route key: dlx_rk

 

Through the above two and two Exchange Queue configuration support make RabbitMQ message expiration q1 q2 is transferred to the rear. So we only use the service to send mission to delay q1, so that the task is triggered due to business code execution monitor (consumption) q2. So basically it enables the creation and expiration task scheduling in distributed environments delay trigger execution.

III. Specific code implementation

1. Create a simple maven project, add the following dependence

    <dependencies>
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.7.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.58</version>
        </dependency>
    </dependencies>

2. The operation of the package used RabbitMQ

. 1  Import com.rabbitmq.client *. ;
 2  
. 3  Import java.io.IOException;
 . 4  Import java.util.concurrent.TimeoutException;
 . 5  
. 6  / ** 
. 7  * 1. connection RabbitMQ
 . 8  * 2. A delay Task
 9  * 3. consumption delay task
 10   * / 
. 11  public  class RabbitMQUtil {
 12 is  
13 is      Private  static connection Conn;
 14      Private  static Channel Channel;
 15  
16      / ** 
. 17       * initialize RabbitMQ connected to Channel
 18 is       * /
19     static {
20         ConnectionFactory factory = new ConnectionFactory();
21         factory.setUsername("guest");
22         factory.setPassword("guest");
23         factory.setVirtualHost("/");
24         factory.setHost("localhost");
25         factory.setPort(5672);
26 
27         try {
28             conn = factory.newConnection();
29             channel = conn.createChannel();
30         } catch (IOException e) {
31             System.out.println("获取RabbitMQ连接失败");
32         } catch (TimeoutException e) {
33             System.out.println("获取RabbitMQ连接超时");
34         }
35     }
36 
37 //    public static void close() throws IOException, TimeoutException {
38 //        if (Objects.nonNull(channel))
39 //            channel.close();
40 //        if (Objects.nonNull(conn))
41 //            conn.close();
42 //    }
43 is  
44 is      / ** 
45       * Key exchange sends a route specified delay task
 46 is       * @param MSG bytes delay task the JSON
 47       * @param exchangeName
 48       * @param routingKey
 49       * @param expiration time delay
 50       * / 
51 is      public  static  void addTask ( byte [] MSG, exchangeName String, String routingKey, int expiration) {
 52 is          the try {
 53 is              channel.basicPublish (exchangeName, routingKey,
 54 is                      new newAMQP.BasicProperties.Builder ()
 55                              .expiration (String.valueOf (expiration))
 56 is                              .build (), MSG);
 57 is          } the catch (IOException E) {
 58              e.printStackTrace ();
 59          }
 60      }
 61 is  
62 is      / * * 
63       * message queue of the specified consumption (delay task)
 64-       * @param queueName
 65       * @param Handler task processor
 66       * @param consumerTag consumer label (multiple consumers simultaneously can use consumerTag distinguish the same message queue)
 67       * /
68     public static void bindConsumer(String queueName, DemoTaskHandler handler, String consumerTag) {
69         try {
70             channel.basicConsume(queueName, false, consumerTag,
71                     new DefaultConsumer(channel) {
72                         @Override
73                         public void handleDelivery(String consumerTag,
74                                                    Envelope envelope,
75                                                    AMQP.BasicProperties properties,
76                                                    byte[] body)
77                                 throws IOException {
78                             long deliveryTag = envelope.getDeliveryTag();
79                             // (process the message components here ...)
80                             handler.execute(body, consumerTag);
81                             channel.basicAck(deliveryTag, false); // 应答,告知queue成功收到消息
82                         }
83                     });
84         } catch (IOException e) {
85             e.printStackTrace();
86         }
87     }
88 
89 }

3. Analog Delay Task POJO

 1 import java.io.Serializable;
 2 
 3 public class DemoTask implements Serializable {
 4 
 5     private int id;
 6 
 7     public int getId() {
 8         return id;
 9     }
10 
11     public void setId(int id) {
12         this.id = id;
13     }
14 }

4. Delay Task Processor

. 1  Import com.alibaba.fastjson.JSON;
 2  
. 3  public  class DemoTaskHandler {
 . 4  
. 5      public  void Execute ( byte [] body, String consumerTag) {
 . 6          DemoTask Task JSON.parseObject = ( new new String (body), DemoTask. Class );
 . 7          System.out.println (consumerTag + "receive delay task id:" + task.getId () + " and processed" );
 8      }
 9 }

5. Design a main delay queue to send to the task q1

. 1  Import com.alibaba.fastjson.JSON;
 2  
. 3  Import java.util.Scanner;
 . 4  
. 5  public  class Producer {
 . 6  
. 7      public  static  void main (String [] args) {
 . 8          // add delay task 
. 9          the System.out. println ( "A delay press the keyboard task" );
 10          Scanner SC = new new Scanner (the System.in);
 . 11          int I =. 1 ;
 12 is          the while (sc.hasNextLine ()) {
 13 is              sc.nextLine ();
 14              DemoTask bo =new new DemoTask ();
 15              bo.setId (I ++ );
 16              RabbitMQUtil.addTask (JSON.toJSONString (BO) .getBytes (),
 . 17                      "ExQ1" ,
 18 is                      "Send" ,
 . 19                      10000 );
 20 is              System.out.println ( "successfully added a task delay" );
 21          }
 22      }
 23 is  
24 }

6. Create two consumers (processing delay the task of business) consumption delay task, distributed simulation environment

. 1  public  class Consumer1 {
 2  
. 3      public  static  void main (String [] args) {
 . 4          // simulate a distributed environment, the processing delay due tasks 
. 5          RabbitMQUtil.bindConsumer ( "Q2" ,
 . 6                  new new DemoTaskHandler (),
 . 7                  " consumer1 " );
 . 8  
. 9      }
 10  
. 11 }
. 1  public  class Consumer2 {
 2  
. 3      public  static  void main (String [] args) {
 . 4          // simulate a distributed environment, the processing delay due tasks 
. 5          RabbitMQUtil.bindConsumer ( "Q2" ,
 . 6                  new new DemoTaskHandler (),
 . 7                  " consumer2 " );
 . 8      }
 . 9 }

7. Run Producer, Consumer1, Consumer2 observations

 

 

 

 

 

 The observation that, after a delay of each transmission job, will be 10 seconds or consumer2 consumer1 consumption, more basically a distributed scheduling delay.

 

Guess you like

Origin www.cnblogs.com/yhcjhun/p/11727906.html