我正在使用Vert.x库打开WebSockets并消耗掉它们的消息。消息处理可能会阻塞,因此我会将这些消息传递给工作线程。我以为它们有一个预定义大小的有界队列,但它只是创建一个LinkedList,如在vertx核心库中的TaskQueue.java中所见:
private final LinkedList<Task> tasks = new LinkedList<>();
结果是,当我的进程成为缓慢的使用者时,没有给源头施加压力,它耗尽了内存-分析堆转储证实了这一点。我正在考虑根本不使用工作线程,尽管对此感到有些惊讶-如果单个套接字发送的数据过多,我们可能想单独施加压力,阻塞事件循环将对其他线程造成不利影响套接字也-也许我丢失了一些东西/没有低估如何正确使用库?
添加:代码段
好的,我有一个MarshallingStage.java
类,已在webSocket上注册为textMessageHandler:
MarshallingStage marshallingStage = new MarshallingStage(ctx);
webSocket.textMessageHandler(marshallingStage);
因此marshallingStage实现了Handler<String>
,它将解组json并将其传递给工作线程。
@Override
public void handle(String text) {
Message message;
try {
message = mUnmarshaller.unmarshall(text);
}
catch (MarshallingException e) {
mCtx.disconnect("failed to unmarshall "+ text, e);
return;
}
if (message != null) {
handleInbound(new MessageEvent(message), mCtx);
}
else {
log.error("{} unmarshalled null message", mCtx.getConnectionId());
}
}
@Override
public void handleInbound(PipelineEvent event, ProviderContext ctx) {
Vertx.currentContext().executeBlocking(
future -> process(event, ctx),
asyncResult -> {}
);
}
鉴于工作线程具有无限制的任务列表,如果事件循环线程消耗tcp缓冲区中的消息的速度快于工作线程消耗该列表中的任务的速度,则该列表将一直增长,直到进程用尽内存。我真的不知道这怎么可能。
答案 0 :(得分:0)
您写错了:
@Override
public void handleInbound(PipelineEvent event, ProviderContext ctx) {
Vertx.currentContext().executeBlocking(
future -> process(event, ctx),
asyncResult -> {}
);
}
处理完成后,您需要实际呼叫future.handle(Future.succeededFuture())
。
@Override
public void handleInbound(PipelineEvent event, ProviderContext ctx) {
Vertx.currentContext().executeBlocking(
future -> { process(event, ctx); future.handle(Future.succeededFuture()); },
asyncResult -> {}
);
}
否则,您将不得不等待释放工作线程。