spring+rabbitmq的简单实现和延迟队列实现

最近项目开发中遇到两个问题,第一个是:订单创建后,5分钟没有付款,则取消订单。第二个是:每天晚上跑spring的定时任务,更新用户的访问次数。由于用户量多,用户访问记录表庞大且是分表,所以更新起来非常耗时,于是决定使用队列解决这两个问题。
使用rabbitmq,设置延时(需额外的插件),可以实现第一个问题。代码中我只需将用户信息取出,然后塞到队列中,由消费者慢慢消化队列,可以缓解第二个问题,下面,我们步入正题。
首先,我们创建一个消息生产者。消息生产者,顾名思义,就是产生消息的bean。我们需要在代码中生成自己需要的信息,可能是多个,以参数的形式,一个一个传递给消息生产者,然后消息生产者将消息一个一个放入队(quque),通过路由器(exchange)再转发给消费者。队列中的信息会一个一个传给消费者,只有消费者处理完这个信息,队列中的下一个信息才会继续传入。

生产者:
import java.io.IOException;
import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.stereotype.Service;

@Service  
public class MessageProducer {

    private Logger logger = LoggerFactory.getLogger(MessageProducer.class);  

    @Resource(name="amqpTemplate")  
    private AmqpTemplate amqpTemplate;

    public void sendMessage(Object message) throws IOException {  
        logger.info("to send message:{}", message); 
        //message是需要传递的信息, 指定特定的queue:queueTestChris
        amqpTemplate.convertAndSend("queueTestChris", message);

    }  
}
接着,创建消费者。作者这里的例子是简单的rabbitmq实现,只创建了一个消费者。实际中,生产者可以对应多个消费者,反之亦然。
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;

public class MessageConsumer implements MessageListener {

    @Override  
    public void onMessage(Message message) {
    //这里是对消息的处理,new String(message.getBody())
         System.out.print(new String(message.getBody()));
    } 
}

生产者和消费者创建完了,下面是最最关键的rabbitmq的配置了

根目录下创建rabbitmq.xml

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit="http://www.springframework.org/schema/rabbit"  
       xsi:schemaLocation="http://www.springframework.org/schema/beans  
     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
     http://www.springframework.org/schema/rabbit  
     http://www.springframework.org/schema/rabbit/spring-rabbit-1.6.xsd">  
    <!--配置connection-factory,指定连接rabbit server参数 -->  
    <rabbit:connection-factory id="connectionFactory"  
                               username="guest" password="guest" host="localhost" port="5672" />  

    <!--定义rabbit template用于数据的接收和发送 -->  
    <rabbit:template id="amqpTemplate" connection-factory="connectionFactory"  
                     exchange="exchangeTest"/>

    <!--通过指定下面的admin信息,当前producer中的exchange和queue会在rabbitmq服务器上自动生成 -->  
    <rabbit:admin id="connectAdmin" connection-factory="connectionFactory"/>  

    <!--定义queue -->  
    <rabbit:queue name="queueChris" durable="true" auto-delete="false" exclusive="false" declared-by="connectAdmin" />

    <!-- 定义direct exchange,绑定queueTest -->  
    <rabbit:direct-exchange name="exchangeTest" durable="true" auto-delete="false" declared-by="connectAdmin" delayed="true">  
        <rabbit:bindings>
            <rabbit:binding queue="queueChris" key="queueTestChris"></rabbit:binding>  
        </rabbit:bindings>
    </rabbit:direct-exchange>  

    <!-- 消息接收者 -->  
    <bean id="receiverChris" class="com.hz.sunday.xlcl.service.mysql.consumer.MessageConsumer"></bean>  

    <!-- queue litener  观察 监听模式 当有消息到达时会通知监听在对应的队列上的监听对象-->  
    <rabbit:listener-container connection-factory="connectionFactory">  
        <rabbit:listener queues="queueChris" ref="receiverChris"/>  
    </rabbit:listener-container>  
</beans> 

然后applicationContext.xml引入:

<import resource="classpath*:rabbitmq.xml" ></import>

<!-- 激活annotation功能 -->  
<context:annotation-config />  
<!-- 激活annotation功能 -->  
<context:spring-configured /> 

然后是代码中调用(这里读者在项目中随便放入哪里触发一下就好了,楼主没写过单元测试…):

for (int i = 0; i < 10; i++)

        {
            // 将消息放入队列,并发送
            messageProducer.sendMessage(i);
        }

可以看到控制台输出0到9.

一个简单的rabbitmq消息队列就完成啦。然后是延时队列的实现,这个比较简单http://www.rabbitmq.com/community-plugins.html网页下载适合的“rabbitmq_delayed_message_exchange插件”,下载完成后将它放到RabbitMQ插件安装目录({rabbitmq-server}/plugins/),然后执行命令rabbitmq-plugins enable rabbitmq_delayed_message_exchange启用插件,执行命令rabbitmq-plugins disable rabbitmq_delayed_message_exchange也可以关闭插件。插件也可以在最后的百度云盘下载。插件安装完成后,修改rabbitmq的配置文件:

 <rabbit:direct-exchange name="exchangeTest" durable="true" auto-delete="false" declared-by="connectAdmin">  
        <rabbit:bindings>
            <rabbit:binding queue="queueChris" key="queueTestChris"></rabbit:binding>  
        </rabbit:bindings>
    </rabbit:direct-exchange>  

新加delayed属性:

  <!-- 定义direct exchange,绑定queueTest -->  
    <rabbit:direct-exchange name="exchangeTest" durable="true" auto-delete="false" declared-by="connectAdmin" delayed="true">  
        <rabbit:bindings>
            <rabbit:binding queue="queueChris" key="queueTestChris"></rabbit:binding>  
        </rabbit:bindings>
    </rabbit:direct-exchange>  

然后生产者添加延时参数:

import java.io.IOException;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.stereotype.Service;


@Service  
public class MessageProducer {

    private Logger logger = LoggerFactory.getLogger(MessageProducer.class);  

    @Resource(name="amqpTemplate")  
    private AmqpTemplate amqpTemplate;

    public void sendMessage(Object message) throws IOException {  
        logger.info("to send message:{}", message);  
        amqpTemplate.convertAndSend("queueTestChris", message,  
                new MessagePostProcessor() {

                @Override  
                public Message postProcessMessage(Message message)  
                    throws AmqpException {  
    //这个直接设置了30秒的延时,读者可以根据需求,将延时以参数形式传递过来
    message.getMessageProperties().setDelay(30000);
                return message;  
                }  
                });

    }  
}  

最后,不要忘了删除原先的exchange和quequ,否则会报错
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
最后重启服务,一切都Ok啦。
最后是rabbitmq、rabbitmq延时插件、opt、所需jar的下载:
链接: https://pan.baidu.com/s/1c26NjhA
密码: kxdx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值