优化MessageConsumer

This commit is contained in:
redkale
2023-10-05 19:47:40 +08:00
parent f4b4609acc
commit e280061dff
8 changed files with 189 additions and 127 deletions

View File

@@ -67,13 +67,14 @@
MQ管理接口配置 MQ管理接口配置
不同MQ节点所配置的MQ集群不能重复。 不同MQ节点所配置的MQ集群不能重复。
MQ跟着协议走所以mq的属性值需要被赋值在rest节点上, 由于SncpServlet是自动生成的故SNCP协议下mq属性值被赋值在service/services节点上 MQ跟着协议走所以mq的属性值需要被赋值在rest节点上, 由于SncpServlet是自动生成的故SNCP协议下mq属性值被赋值在service/services节点上
name: 服务的名称用于监控识别多个mq节点时只能有一个name为空的节点mq.name不能重复,命名规则: 字母、数字、下划线 name: 服务的名称用于监控识别多个mq节点时只能有一个name为空的节点mq.name不能重复,命名规则: 字母、数字、下划线
type 实现类名必须是org.redkale.mq.MessageAgent的子类 type 实现类名必须是org.redkale.mq.MessageAgent的子类
coder: MessageRecord的解析器类必须是org.redkale.mq.MessageCoder<MessageRecord>的实现类, threads线程数为0表示使用workExecutor。默认: CPU核数, 核数=1的情况下默认值为2JDK 21以上版本默认使用虚拟线程池
可对数据包进行加密解密默认值org.redkale.mq.MessageRecordCoder coder: MessageRecord的解析器类必须是org.redkale.mq.MessageCoder<MessageRecord>的实现类,
可对数据包进行加密解密默认值org.redkale.mq.MessageRecordCoder
MQ节点下的子节点配置没有固定格式, 根据MessageAgent实现方的定义来配置 MQ节点下的子节点配置没有固定格式, 根据MessageAgent实现方的定义来配置
--> -->
<mq name="" type="org.redkalex.mq.kafka.KafkaMessageAgent"> <mq name="" type="org.redkalex.mq.kafka.KafkaMessageAgent" threads="4">
<servers value="127.0.0.1:9101"/> <servers value="127.0.0.1:9101"/>
<!-- <!--
加载所有的MessageConsumer实例; 加载所有的MessageConsumer实例;

View File

@@ -1656,7 +1656,7 @@ public final class Application {
long s = System.currentTimeMillis(); long s = System.currentTimeMillis();
final StringBuffer sb = new StringBuffer(); final StringBuffer sb = new StringBuffer();
Set<String> names = new HashSet<>(); Set<String> names = new HashSet<>();
ResourceFactory resourceFactory = ResourceFactory.create(); ResourceFactory resourceFactory = this.resourceFactory.createChild();
List<ResourceFactory> factorys = new ArrayList<>(); List<ResourceFactory> factorys = new ArrayList<>();
for (NodeServer ns : this.servers) { for (NodeServer ns : this.servers) {
factorys.add(ns.getResourceFactory()); factorys.add(ns.getResourceFactory());
@@ -2658,13 +2658,14 @@ public final class Application {
this.clientAsyncGroup.dispose(); this.clientAsyncGroup.dispose();
logger.info("AsyncGroup destroy in " + (System.currentTimeMillis() - s) + " ms"); logger.info("AsyncGroup destroy in " + (System.currentTimeMillis() - s) + " ms");
} }
if (this.workExecutor != null) {
this.workExecutor.shutdownNow();
}
long intms = System.currentTimeMillis() - f; long intms = System.currentTimeMillis() - f;
String ms = String.valueOf(intms); String ms = String.valueOf(intms);
int repeat = ms.length() > 7 ? 0 : (7 - ms.length()) / 2; int repeat = ms.length() > 7 ? 0 : (7 - ms.length()) / 2;
logger.info(colorMessage(logger, 36, 1, "-".repeat(repeat) + "------------------------ Redkale shutdown in " + ms + " ms " + (ms.length() / 2 == 0 ? " " : "") + "-".repeat(repeat) + "------------------------") + "\r\n" + "\r\n"); logger.info(colorMessage(logger, 36, 1, "-".repeat(repeat) + "------------------------ Redkale shutdown in " + ms + " ms " + (ms.length() / 2 == 0 ? " " : "") + "-".repeat(repeat) + "------------------------") + "\r\n" + "\r\n");
LoggingBaseHandler.traceFlag = true; LoggingBaseHandler.traceFlag = true;
} }
public ExecutorService getWorkExecutor() { public ExecutorService getWorkExecutor() {

View File

@@ -650,27 +650,10 @@ public abstract class NodeServer {
if (Modifier.isAbstract(serviceImplClass.getModifiers()) || Modifier.isInterface(serviceImplClass.getModifiers())) { if (Modifier.isAbstract(serviceImplClass.getModifiers()) || Modifier.isInterface(serviceImplClass.getModifiers())) {
return false; return false;
} }
if (MessageConsumer.class.isAssignableFrom(serviceImplClass)) {
ResourceConsumer mqConsumer = serviceImplClass.getAnnotation(ResourceConsumer.class);
if (mqConsumer == null) {
return false;
}
MessageAgent mqAgent = application.getMessageAgent(mqConsumer.mq());
if (mqAgent == null) {
logger.info("not found MessageAgent(mq = " + mqConsumer.mq() + ")");
return false;
}
}
return true; return true;
} }
protected boolean interceptComponent(Service service) { protected boolean interceptComponent(Service service) {
if (service instanceof MessageConsumer) {
ResourceConsumer mqConsumer = service.getClass().getAnnotation(ResourceConsumer.class);
MessageAgent mqAgent = application.getMessageAgent(mqConsumer.mq());
mqAgent.addMessageConsumer(mqConsumer, (MessageConsumer) service);
return true;
}
return false; return false;
} }

View File

@@ -5,11 +5,14 @@
*/ */
package org.redkale.mq; package org.redkale.mq;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import java.util.function.IntFunction;
import java.util.logging.*; import java.util.logging.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.redkale.annotation.*; import org.redkale.annotation.*;
@@ -22,6 +25,7 @@ import org.redkale.convert.Convert;
import org.redkale.convert.ConvertFactory; import org.redkale.convert.ConvertFactory;
import org.redkale.convert.ConvertType; import org.redkale.convert.ConvertType;
import org.redkale.net.Servlet; import org.redkale.net.Servlet;
import org.redkale.net.WorkThread;
import org.redkale.net.http.*; import org.redkale.net.http.*;
import org.redkale.net.sncp.*; import org.redkale.net.sncp.*;
import org.redkale.service.*; import org.redkale.service.*;
@@ -54,44 +58,52 @@ public abstract class MessageAgent implements Resourcable {
protected AnyValue config; protected AnyValue config;
private ExecutorService workExecutor;
protected final ReentrantLock messageProducerLock = new ReentrantLock(); protected final ReentrantLock messageProducerLock = new ReentrantLock();
protected MessageProducer baseMessageProducer; protected MessageProducer messageBaseProducer;
protected Map<ConvertType, ConvertMessageProducer> messageProducers = new ConcurrentHashMap<>(); protected Map<ConvertType, ConvertMessageProducer> messageProducerMap = new ConcurrentHashMap<>();
protected final CopyOnWriteArrayList<MessageConsumer> messageConsumerList = new CopyOnWriteArrayList<>();
//key: group, sub-key: topic //key: group, sub-key: topic
protected final ConcurrentHashMap<String, ConcurrentHashMap<String, MessageConsumer>> consumerMap = new ConcurrentHashMap<>(); protected final Map<String, Map<String, MessageConsumerWrapper>> messageConsumerMap = new HashMap<>();
protected final CopyOnWriteArrayList<MessageConsumer> consumerList = new CopyOnWriteArrayList<>(); protected MessageClientProducer httpClientProducer;
protected MessageClientProducer httpProducer; protected MessageClientProducer sncpClientProducer;
protected MessageClientProducer sncpProducer;
protected HttpMessageClient httpMessageClient; protected HttpMessageClient httpMessageClient;
protected SncpMessageClient sncpMessageClient; protected SncpMessageClient sncpMessageClient;
protected final ReentrantLock consumerLock = new ReentrantLock(); protected final ReentrantLock clientConsumerLock = new ReentrantLock();
protected final ReentrantLock producerLock = new ReentrantLock(); protected final ReentrantLock clientProducerLock = new ReentrantLock();
protected final ReentrantLock serviceLock = new ReentrantLock(); protected final ReentrantLock serviceLock = new ReentrantLock();
protected final List<MessageConsumer> consumerListeners = new CopyOnWriteArrayList<>(); protected MessageCoder<MessageRecord> clientMessageCoder = MessageRecordCoder.getInstance();
//本地Service消息接收处理器 key:consumerid
protected HashMap<String, MessageClientConsumerNode> clientConsumerNodes = new LinkedHashMap<>();
protected final AtomicLong msgSeqno = new AtomicLong(System.nanoTime()); protected final AtomicLong msgSeqno = new AtomicLong(System.nanoTime());
protected ScheduledThreadPoolExecutor timeoutExecutor; protected ScheduledThreadPoolExecutor timeoutExecutor;
protected MessageCoder<MessageRecord> messageCoder = MessageRecordCoder.getInstance();
//本地Service消息接收处理器 key:consumerid
protected HashMap<String, MessageClientConsumerNode> clientConsumerNodes = new LinkedHashMap<>();
public void init(AnyValue config) { public void init(AnyValue config) {
this.name = checkName(config.getValue("name", "")); this.name = checkName(config.getValue("name", ""));
int threads = config.getIntValue("threads", -1);
if (threads == 0) {
this.workExecutor = application.getWorkExecutor();
}
if (this.workExecutor == null) {
this.workExecutor = threads > 0 ? WorkThread.createExecutor(threads, "Redkale-MessageConsumerThread-[" + name + "]-%s")
: WorkThread.createWorkExecutor(Utility.cpus(), "Redkale-MessageConsumerThread-[" + name + "]-%s");
}
this.httpMessageClient = new HttpMessageClient(this); this.httpMessageClient = new HttpMessageClient(this);
this.sncpMessageClient = new SncpMessageClient(this); this.sncpMessageClient = new SncpMessageClient(this);
String coderType = config.getValue("coder", ""); String coderType = config.getValue("coder", "");
@@ -106,7 +118,7 @@ public abstract class MessageAgent implements Resourcable {
if (coder instanceof Service) { if (coder instanceof Service) {
((Service) coder).init(config); ((Service) coder).init(config);
} }
this.messageCoder = coder; this.clientMessageCoder = coder;
} catch (RuntimeException ex) { } catch (RuntimeException ex) {
throw ex; throw ex;
} catch (Exception e) { } catch (Exception e) {
@@ -122,13 +134,17 @@ public abstract class MessageAgent implements Resourcable {
this.timeoutExecutor.setRemoveOnCancelPolicy(true); this.timeoutExecutor.setRemoveOnCancelPolicy(true);
} }
public Future submit(Runnable event) {
return workExecutor.submit(event);
}
public Map<String, Long> start(List<MessageConsumer> consumers) { public Map<String, Long> start(List<MessageConsumer> consumers) {
this.consumerListeners.addAll(consumers); initMessageConsumer(consumers);
startMessageConsumer();
final LinkedHashMap<String, Long> map = new LinkedHashMap<>(); final LinkedHashMap<String, Long> map = new LinkedHashMap<>();
final List<CompletableFuture> futures = new ArrayList<>();
this.clientConsumerNodes.values().forEach(node -> { this.clientConsumerNodes.values().forEach(node -> {
long s = System.currentTimeMillis(); long s = System.currentTimeMillis();
node.consumer.startup(); node.consumer.start();
long e = System.currentTimeMillis() - s; long e = System.currentTimeMillis() - s;
map.put(node.consumer.consumerid, e); map.put(node.consumer.consumerid, e);
}); });
@@ -137,30 +153,37 @@ public abstract class MessageAgent implements Resourcable {
//Application.shutdown 在执行server.shutdown之前执行 //Application.shutdown 在执行server.shutdown之前执行
public void stop() { public void stop() {
this.stopMessageConsumer();
this.stopMessageProducer();
this.clientConsumerNodes.values().forEach(node -> { this.clientConsumerNodes.values().forEach(node -> {
node.consumer.shutdown(); node.consumer.stop();
}); });
} }
//Application.shutdown 在所有server.shutdown执行后执行 //Application.shutdown 在所有server.shutdown执行后执行
public void destroy(AnyValue config) { public void destroy(AnyValue config) {
this.httpMessageClient.close(); for (MessageConsumer consumer : messageConsumerList) {
this.sncpMessageClient.close();
for (MessageConsumer consumer : consumerListeners) {
consumer.destroy(config); consumer.destroy(config);
} }
this.consumerListeners.clear(); this.messageConsumerList.clear();
this.messageConsumerMap.clear();
this.httpMessageClient.close();
this.sncpMessageClient.close();
if (this.sncpClientProducer != null) {
this.sncpClientProducer.shutdown();
}
if (this.httpClientProducer != null) {
this.httpClientProducer.shutdown();
}
if (this.clientMessageCoder instanceof Service) {
((Service) this.clientMessageCoder).destroy(config);
}
if (this.timeoutExecutor != null) { if (this.timeoutExecutor != null) {
this.timeoutExecutor.shutdown(); this.timeoutExecutor.shutdownNow();
} }
if (this.sncpProducer != null) { if (this.workExecutor != null && this.workExecutor != application.getWorkExecutor()) {
this.sncpProducer.shutdown().join(); this.workExecutor.shutdownNow();
}
if (this.httpProducer != null) {
this.httpProducer.shutdown().join();
}
if (this.messageCoder instanceof Service) {
((Service) this.messageCoder).destroy(config);
} }
} }
@@ -169,25 +192,55 @@ public abstract class MessageAgent implements Resourcable {
} }
public MessageProducer loadMessageProducer(ResourceProducer ann) { public MessageProducer loadMessageProducer(ResourceProducer ann) {
MessageProducer baseProducer = this.baseMessageProducer; MessageProducer baseProducer = this.messageBaseProducer;
if (this.baseMessageProducer == null) { if (this.messageBaseProducer == null) {
messageProducerLock.lock(); messageProducerLock.lock();
try { try {
if (this.baseMessageProducer == null) { if (this.messageBaseProducer == null) {
this.baseMessageProducer = createMessageProducer(); startMessageProducer();
} }
} finally { } finally {
messageProducerLock.unlock(); messageProducerLock.unlock();
} }
baseProducer = this.baseMessageProducer; baseProducer = this.messageBaseProducer;
} }
MessageProducer producer = baseProducer; MessageProducer producer = baseProducer;
Objects.requireNonNull(producer); Objects.requireNonNull(producer);
return messageProducers.computeIfAbsent(ann.convertType(), t -> new ConvertMessageProducer(producer, ConvertFactory.findConvert(t))); return messageProducerMap.computeIfAbsent(ann.convertType(), t -> new ConvertMessageProducer(producer, ConvertFactory.findConvert(t)));
} }
public void loadMessageConsumer(MessageConsumer consumer) { protected void initMessageConsumer(List<MessageConsumer> consumers) {
clientConsumerLock.lock();
try {
Map<String, Map<String, MessageConsumerWrapper>> maps = new HashMap<>();
for (MessageConsumer consumer : consumers) {
ResourceConsumer res = consumer.getClass().getAnnotation(ResourceConsumer.class);
String group = application.getPropertyValue(res.group());
group = consumer.getClass().getName() + (group.isEmpty() ? "" : ("-" + group));
Map<String, MessageConsumerWrapper> map = maps.computeIfAbsent(group, g -> new HashMap<>());
for (String t : res.topics()) {
String topic = application.getPropertyValue(t);
if (!topic.trim().isEmpty()) {
if (map.containsKey(topic.trim())) {
throw new RedkaleException(MessageConsumer.class.getSimpleName()
+ " consume topic (" + topic + ") repeat with " + map.get(topic).getClass().getName() + " and " + consumer.getClass().getName());
}
for (MessageConsumerWrapper wrapper : map.values()) {
if (!Objects.equals(res.convertType(), wrapper.convertType)) {
throw new RedkaleException(MessageConsumer.class.getSimpleName()
+ " " + consumer.getClass().getName() + " convertType(" + res.convertType() + ") differ in "
+ wrapper.consumer.getClass().getName() + " convertType(" + wrapper.convertType + ")");
}
}
map.put(topic.trim(), new MessageConsumerWrapper(this, consumer, res.convertType()));
}
}
}
messageConsumerList.addAll(consumers);
messageConsumerMap.putAll(maps);
} finally {
clientConsumerLock.unlock();
}
} }
@Override @Override
@@ -211,6 +264,10 @@ public abstract class MessageAgent implements Resourcable {
this.config = config; this.config = config;
} }
public ExecutorService getWorkExecutor() {
return workExecutor;
}
public HttpMessageClient getHttpMessageClient() { public HttpMessageClient getHttpMessageClient() {
return httpMessageClient; return httpMessageClient;
} }
@@ -234,7 +291,6 @@ public abstract class MessageAgent implements Resourcable {
return name; return name;
} }
@Deprecated
protected List<MessageClientConsumer> getMessageClientConsumers() { protected List<MessageClientConsumer> getMessageClientConsumers() {
List<MessageClientConsumer> consumers = new ArrayList<>(); List<MessageClientConsumer> consumers = new ArrayList<>();
MessageClientConsumer one = this.httpMessageClient == null ? null : this.httpMessageClient.respConsumer; MessageClientConsumer one = this.httpMessageClient == null ? null : this.httpMessageClient.respConsumer;
@@ -249,14 +305,13 @@ public abstract class MessageAgent implements Resourcable {
return consumers; return consumers;
} }
@Deprecated
protected List<MessageClientProducer> getMessageClientProducers() { protected List<MessageClientProducer> getMessageClientProducers() {
List<MessageClientProducer> producers = new ArrayList<>(); List<MessageClientProducer> producers = new ArrayList<>();
if (this.httpProducer != null) { if (this.httpClientProducer != null) {
producers.add(this.httpProducer); producers.add(this.httpClientProducer);
} }
if (this.sncpProducer != null) { if (this.sncpClientProducer != null) {
producers.add(this.sncpProducer); producers.add(this.sncpClientProducer);
} }
MessageClientProducer one = this.httpMessageClient == null ? null : this.httpMessageClient.getProducer(); MessageClientProducer one = this.httpMessageClient == null ? null : this.httpMessageClient.getProducer();
if (one != null) { if (one != null) {
@@ -269,56 +324,57 @@ public abstract class MessageAgent implements Resourcable {
return producers; return producers;
} }
@Deprecated public MessageCoder<MessageRecord> getClientMessageCoder() {
public MessageCoder<MessageRecord> getMessageCoder() { return this.clientMessageCoder;
return this.messageCoder;
} }
@Deprecated
//获取指定topic的生产处理器 //获取指定topic的生产处理器
public MessageClientProducer getSncpMessageClientProducer() { public MessageClientProducer getSncpMessageClientProducer() {
if (this.sncpProducer == null) { if (this.sncpClientProducer == null) {
producerLock.lock(); clientProducerLock.lock();
try { try {
if (this.sncpProducer == null) { if (this.sncpClientProducer == null) {
long s = System.currentTimeMillis(); long s = System.currentTimeMillis();
this.sncpProducer = createMessageClientProducer("SncpProducer"); this.sncpClientProducer = createMessageClientProducer("SncpProducer");
long e = System.currentTimeMillis() - s; long e = System.currentTimeMillis() - s;
if (logger.isLoggable(Level.FINEST)) { if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "MessageAgent.SncpProducer startup all in " + e + "ms"); logger.log(Level.FINEST, "MessageAgent.SncpProducer startup all in " + e + "ms");
} }
} }
} finally { } finally {
producerLock.unlock(); clientProducerLock.unlock();
} }
} }
return this.sncpProducer; return this.sncpClientProducer;
} }
@Deprecated
public MessageClientProducer getHttpMessageClientProducer() { public MessageClientProducer getHttpMessageClientProducer() {
if (this.httpProducer == null) { if (this.httpClientProducer == null) {
producerLock.lock(); clientProducerLock.lock();
try { try {
if (this.httpProducer == null) { if (this.httpClientProducer == null) {
long s = System.currentTimeMillis(); long s = System.currentTimeMillis();
this.httpProducer = createMessageClientProducer("HttpProducer"); this.httpClientProducer = createMessageClientProducer("HttpProducer");
long e = System.currentTimeMillis() - s; long e = System.currentTimeMillis() - s;
if (logger.isLoggable(Level.FINEST)) { if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "MessageAgent.HttpProducer startup all in " + e + "ms"); logger.log(Level.FINEST, "MessageAgent.HttpProducer startup all in " + e + "ms");
} }
} }
} finally { } finally {
producerLock.unlock(); clientProducerLock.unlock();
} }
} }
return this.httpProducer; return this.httpClientProducer;
} }
// //
protected abstract MessageProducer createMessageProducer(); protected abstract void startMessageConsumer();
protected abstract void closeMessageProducer(MessageProducer messageProducer) throws Exception; protected abstract void stopMessageConsumer();
protected abstract void startMessageProducer();
protected abstract void stopMessageProducer();
@ResourceListener @ResourceListener
public abstract void onResourceChange(ResourceEvent[] events); public abstract void onResourceChange(ResourceEvent[] events);
@@ -335,33 +391,12 @@ public abstract class MessageAgent implements Resourcable {
//ServiceLoader时判断配置是否符合当前实现类 //ServiceLoader时判断配置是否符合当前实现类
public abstract boolean acceptsConf(AnyValue config); public abstract boolean acceptsConf(AnyValue config);
@Deprecated
//创建指定topic的生产处理器 //创建指定topic的生产处理器
protected abstract MessageClientProducer createMessageClientProducer(String producerName); protected abstract MessageClientProducer createMessageClientProducer(String producerName);
//创建指定topic的消费处理器 //创建指定topic的消费处理器
public abstract MessageClientConsumer createMessageClientConsumer(String[] topics, String group, MessageClientProcessor processor); public abstract MessageClientConsumer createMessageClientConsumer(String[] topics, String group, MessageClientProcessor processor);
public void addMessageConsumer(ResourceConsumer res, MessageConsumer consumer) {
consumerLock.lock();
try {
ConcurrentHashMap<String, MessageConsumer> map = consumerMap.computeIfAbsent(res.group(), g -> new ConcurrentHashMap<>());
for (String topic : res.topics()) {
if (!topic.trim().isEmpty()) {
if (map.containsKey(topic.trim())) {
throw new RedkaleException(MessageConsumer.class.getSimpleName()
+ " consume topic (" + topic + ") repeat with "
+ map.get(topic).getClass().getName() + " and " + consumer.getClass().getName());
}
map.put(topic.trim(), consumer);
}
}
consumerList.add(consumer);
} finally {
consumerLock.unlock();
}
}
public final void putService(NodeHttpServer ns, Service service, HttpServlet servlet) { public final void putService(NodeHttpServer ns, Service service, HttpServlet servlet) {
AutoLoad al = service.getClass().getAnnotation(AutoLoad.class); AutoLoad al = service.getClass().getAnnotation(AutoLoad.class);
if (al != null && !al.value() && service.getClass().getAnnotation(Local.class) != null) { if (al != null && !al.value() && service.getClass().getAnnotation(Local.class) != null) {
@@ -471,21 +506,68 @@ public abstract class MessageAgent implements Resourcable {
} }
protected static class MessageConsumerWrapper { public static class MessageConsumerWrapper<T> {
private final MessageAgent messageAgent;
private final MessageConsumer consumer; private final MessageConsumer consumer;
public MessageConsumerWrapper(MessageConsumer consumer) { private final ConvertType convertType;
private final Convert convert;
private final Type messageType;
private final IntFunction<T[]> arrayCreator;
public MessageConsumerWrapper(MessageAgent messageAgent, MessageConsumer<T> consumer, ConvertType convertType) {
Objects.requireNonNull(messageAgent);
Objects.requireNonNull(consumer); Objects.requireNonNull(consumer);
Objects.requireNonNull(convertType);
this.messageAgent = messageAgent;
this.convertType = convertType;
this.consumer = consumer; this.consumer = consumer;
this.convert = ConvertFactory.findConvert(convertType);
this.messageType = parseMessageType(consumer.getClass());
this.arrayCreator = Creator.funcArray(TypeToken.typeToClass(messageType));
}
private static Type parseMessageType(Class<? extends MessageConsumer> clazz) {
if (Objects.equals(Object.class, clazz)) {
throw new RedkaleException(clazz.getName() + " not implements " + MessageConsumer.class.getName());
}
Type messageType = null;
Class[] clzs = clazz.getInterfaces();
for (int i = 0; i < clzs.length; i++) {
if (MessageConsumer.class.isAssignableFrom(clzs[i])) {
messageType = clazz.getGenericInterfaces()[i];
break;
}
}
if (messageType == null) {
return parseMessageType((Class) clazz.getSuperclass());
}
return TypeToken.getGenericType(((ParameterizedType) messageType).getActualTypeArguments()[0], clazz);
} }
public void init(AnyValue config) { public void init(AnyValue config) {
consumer.init(config); consumer.init(config);
} }
public void onMessage(MessageConext context, Object[] messages) { public Future onMessage(MessageConext context, List<byte[]> messages) {
consumer.onMessage(context, messages); return messageAgent.submit(() -> {
try {
T[] msgs = this.arrayCreator.apply(messages.size());
int index = -1;
for (byte[] bs : messages) {
msgs[++index] = (T) convert.convertFrom(messageType, bs);
}
consumer.onMessage(context, msgs);
} catch (Throwable t) {
messageAgent.getLogger().log(Level.SEVERE, MessageConsumer.class.getSimpleName() + " execute error, topic: " + context.getTopic()
+ ", messages: " + messages.stream().map(v -> new String(v, StandardCharsets.UTF_8)).collect(Collectors.toList()));
}
});
} }
public void destroy(AnyValue config) { public void destroy(AnyValue config) {

View File

@@ -51,7 +51,7 @@ public abstract class MessageClient {
protected void close() { protected void close() {
if (this.respConsumer != null) { if (this.respConsumer != null) {
this.respConsumer.shutdown(); this.respConsumer.stop();
} }
} }
@@ -100,7 +100,7 @@ public abstract class MessageClient {
}; };
long ones = System.currentTimeMillis(); long ones = System.currentTimeMillis();
MessageClientConsumer one = messageAgent.createMessageClientConsumer(new String[]{appRespTopic}, appRespConsumerid, processor); MessageClientConsumer one = messageAgent.createMessageClientConsumer(new String[]{appRespTopic}, appRespConsumerid, processor);
one.startup(); one.start();
long onee = System.currentTimeMillis() - ones; long onee = System.currentTimeMillis() - ones;
if (finest) { if (finest) {
messageAgent.logger.log(Level.FINEST, clazzName + ".MessageRespFutureNode.startup " + onee + "ms "); messageAgent.logger.log(Level.FINEST, clazzName + ".MessageRespFutureNode.startup " + onee + "ms ");

View File

@@ -52,9 +52,9 @@ public abstract class MessageClientConsumer {
return topics; return topics;
} }
public abstract void startup(); public abstract void start();
public abstract void shutdown(); public abstract void stop();
public boolean isClosed() { public boolean isClosed() {
return closed; return closed;

View File

@@ -33,9 +33,9 @@ public abstract class MessageClientProducer {
public abstract CompletableFuture<Void> apply(MessageRecord message); public abstract CompletableFuture<Void> apply(MessageRecord message);
public abstract CompletableFuture<Void> startup(); public abstract void startup();
public abstract CompletableFuture<Void> shutdown(); public abstract void shutdown();
public boolean isClosed() { public boolean isClosed() {
return closed.get(); return closed.get();

View File

@@ -58,9 +58,4 @@ public @interface Cacheable {
*/ */
boolean direct() default false; boolean direct() default false;
@Deprecated
boolean sequent() default false;
@Deprecated
boolean continuousid() default false;
} }