优化MessageConsumer
This commit is contained in:
@@ -69,11 +69,12 @@
|
|||||||
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的子类
|
||||||
|
threads:线程数,为0表示使用workExecutor。默认: CPU核数, 核数=1的情况下默认值为2,JDK 21以上版本默认使用虚拟线程池
|
||||||
coder: MessageRecord的解析器类,必须是org.redkale.mq.MessageCoder<MessageRecord>的实现类,
|
coder: MessageRecord的解析器类,必须是org.redkale.mq.MessageCoder<MessageRecord>的实现类,
|
||||||
可对数据包进行加密解密,默认值:org.redkale.mq.MessageRecordCoder
|
可对数据包进行加密解密,默认值: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实例;
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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 ");
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user