@Slf4j
@Component
public class MessageConsumer {
@Autowired
private PpcRequestMessageListener ppcRequestMessageListener; @Autowired
private RabbitTemplate rabbitTemplate; @Autowired
private MessageConverter messageConverter; @Value("${app.rabbitmq.schedule.queue.ppc-request}")
private String ppcRequestQueue; private ExecutorService executor = new ThreadPoolExecutor(1, 4, 60, TimeUnit.SECONDS,
new SynchronousQueue<>(), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy()); public void start() {
Executors.newSingleThreadExecutor().execute(() -> {
try {
while (true) {
ChannelCallbackImpl<PpcRequestMessage> callback = new ChannelCallbackImpl<>(ppcRequestQueue, 4);
List<PpcRequestMessage> list = rabbitTemplate.execute(callback);
if (list == null || list.isEmpty()) {
TimeUnit.MILLISECONDS.sleep(1000);
}
}
} catch (Exception e) {
log.error("MessageConsumer handle error", e);
}
});
} private class ChannelCallbackImpl<T> implements ChannelCallback<List<T>> {
private final MessagePropertiesConverter messagePropertiesConverter = new DefaultMessagePropertiesConverter(); private final String queueName; private final int maxCount; public ChannelCallbackImpl(String queueName, int maxCount) {
this.queueName = queueName;
this.maxCount = maxCount;
} @Override
public List<T> doInRabbit(Channel channel) throws Exception {
GetResponse response = channel.basicGet(queueName, false);
if(response == null){
return null;
}
//如果没有空闲进程,睡眠直至有可用线程
Integer tid = getSetIdleTid(); int total = response.getMessageCount() + 1;
if(total > maxCount){
total = maxCount;
} long[] tags = new long[total];
List<T> messages = new ArrayList<>(total); for (int i = 0; i < total; i++) {
MessageProperties props = messagePropertiesConverter.toMessageProperties(response.getProps(), response.getEnvelope(), "UTF-8");
if (response.getMessageCount() >= 0) {
props.setMessageCount(response.getMessageCount());
}
Message message = new Message(response.getBody(), props);
T t = (T) messageConverter.fromMessage(message);
messages.add(t);
tags[i] = response.getEnvelope().getDeliveryTag();
response = channel.basicGet(queueName, false);
} //accept
for (int i = 0; i < messages.size(); i++) {
executor.execute(new ConsumerAcceptRunnable(tid, channel, tags[i], messages.get(i)));
tid = getSetIdleTid();
} //ack
for (long tag : tags){
channel.basicAck(tag, false);
}
return messages;
} private Integer getSetIdleTid() throws Exception {
Integer tid = PpcProcessStatus.getSetIdleTid();
while (tid == null) {
log.info("ppc process has no idle thread, sleep");
TimeUnit.MILLISECONDS.sleep(500);
continue;
}
return tid;
} public class ConsumerAcceptRunnable implements Runnable{
private final Integer tid;
private final Channel channel;
private final long tag;
private final T t; public ConsumerAcceptRunnable(Integer tid, Channel channel, long tag, T t) {
this.tid = tid;
this.channel = channel;
this.tag = tag;
this.t = t;
} @Override
public void run() {
try {
ppcRequestMessageListener.handleMessage(tid, t);
} catch (Exception e) {
log.error("accept message error {}", t, e);
try {
channel.basicNack(tag, false, true);
} catch (Exception ioe) {
log.error("basicNack error", ioe);
}
}
}
}
}
}

MessageConsumer的更多相关文章

  1. 46.ActiveMQ开篇(Hello World、安全认证、Connection、Session、MessageProducer、MessageConsumer)

    要给有能力的人足够的发挥空间,公司可以养一些能力平平甚至是混日子的人,但绝不能让这些人妨碍有能力的人,否则这样的环境不留也罢. 一.背景介绍 CORBA\DCOM\RMI等RPC中间件技术已经广泛应用 ...

  2. Java消息队列--ActiveMq 实战

    1.下载安装ActiveMQ ActiveMQ官网下载地址:http://activemq.apache.org/download.html ActiveMQ 提供了Windows 和Linux.Un ...

  3. Java消息队列--JMS概述

    1.什么是JMS JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送 ...

  4. (jms)ActiveMQ 安装配置.

    前言 ActiveMQ他是Apache出品的一个JMS提供者,管理会话和队列,运行在JVM下,支持多种语言,如JAVA,C++,C#,应用协议: OpenWire,Stomp REST,WS Noti ...

  5. ActiveMQ消息队列的使用及应用

    这里就不说怎么安装了,直接解压出来就行了. 谢绝转载,作者保留所有权力 目录:  一:JMQ的两种消息模式 1.1:点对点的消息模式 1.2:订阅模式 二:点对点的实现代码 2.1:点对点的发送端 2 ...

  6. ActiveMQ(li)

    一.ActiveMQ 首先,ActiveMQ不是一个框架,它不是struct,webx,netty这种框架,它更像是tomcat服务器,因为你使用它之前必须启动它,activeMQ和JMS的关系有点类 ...

  7. ActiveMQ笔记(1):编译、安装、示例代码

    一.编译 虽然ActiveMQ提供了发布版本,但是建议同学们自己下载源代码编译,以后万一有坑,还可以尝试自己改改源码. 1.1 https://github.com/apache/activemq/r ...

  8. ActiveMQ入门实例Demo

    前面我们已经搭建和配置好了ActiveMQ,下面来看一个Demo,体验一下MQ. JMS 消息模型 JMS消息服务应用程序结构支持两种模型:点对点模型,发布者/订阅者模型. (1)点对点模型(Queu ...

  9. ActiveMQ入门

    ActiveMQ简介 概要 开源 JMS-compliant 消息中间件message-oriented middleware(MOM) 松耦合,相对于RPC的紧耦合 发送消息fire-and-for ...

  10. ActiveMQ中的Destination高级特性(一)

    ---------------------------------------------------------------------------------------- Destination ...

随机推荐

  1. spring boot 与spring boot admin整合问题处理

    1.在整合springboot admin server时,发现admin client无法注册到admin server上 查找原因后发现代码中报错:HttpMediaTypeNotAcceptab ...

  2. WebAssembly 基础以及结合其他编程语言

    0x00 WebAssembly 基础 详情参考<WebAssembly | MDN> (1)概述 WebAssembly 简称 WASM 或 WA,是一种新的编码方式,可以在现代的 We ...

  3. mysql进阶-锁

    锁 概述 锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源(CPU.RAM.I/O)的争用以外,数据也是一种供许多用户共享的资源. 如何保证数据并发访问的一致性.有效性 ...

  4. Oracle 11.2 RAC 删除节点

    软硬件环境:与上一篇文章一致: 一般对 CRS 层面数据结构做重要操作之前一定要先备份 OCR  [root@vastdata4 ~]# ocrconfig -manualbackup vastdat ...

  5. 线性枚举(C语言)

    1.求最大值 比如求一个线性表中的最大值,可以先设定一个最大值,把它初始化为一个非常小的数,然后遍历给定的线性表,将其中的每个元素和目前的最大值比较,如果比它大,则更新这个最大值: 如果比它小,就不做 ...

  6. 初识GO语言--函数

  7. 强化学习:gym下atari游戏环境的官方文档地址

    2024年10月16日 共建议查看两个历史上的官方地址: https://ale.farama.org/ https://www.gymlibrary.dev/ 最新官方地址: https://ale ...

  8. 1000%增长!我仅用一个小时搞定!AI智能体+AI小程序=MVP王炸组合!

    前言 在万圣节的前一晚上10月30日,一位运营朋友跟我说了个点子万圣节头像生成器,然后大概给我分析了下整体思路,于是我用扣子Coze平台(coze.cn)搭建了一个AI智能体整个过程花了一个小时就搞定 ...

  9. Nuxt.js 应用中的 schema:resolved 事件钩子详解

    title: Nuxt.js 应用中的 schema:resolved 事件钩子详解 date: 2024/11/13 updated: 2024/11/13 author: cmdragon exc ...

  10. 『玩转Streamlit』--交互类组件

    交互类组件在Web应用程序中至关重要,它们允许用户与应用进行实时互动,能够显著提升用户体验. 用户不再只是被动地接收信息,而是可以主动地输入数据.做出选择或触发事件,从而更加深入地参与到应用中来. 此 ...