【问题标题】:Java GRPC spawns to many new threads (Minecraft Spigot Plugin)Java GRPC 产生许多新线程(Minecraft Spigot 插件)
【发布时间】:2020-10-30 15:25:04
【问题描述】:

我正在编写一个通过 GRPC 发送和接收消息的 Spigot 插件。 我的问题是,在查看时间后服务器崩溃,因为该进程无法为新线程打开更多文件句柄。 从查看一些线程转储来看,GRPC 似乎每秒产生多个线程而从未关闭它们。 我用来接收消息流的代码如下所示:

public class GRPCMessageReceiver extends BukkitRunnable {

ChatSyncGrpc.ChatSyncBlockingStub chatSync;
LockedQueue lockedQueue = new LockedQueue();
Iterator<ChatMessage> receivingIterator;

public GRPCMessageReceiver(ChatSyncGrpc.ChatSyncBlockingStub chatSync, LockedQueue queue){
    lockedQueue = queue;
    this.chatSync = chatSync;
}

@Override
public void run() {
    if (receivingIterator == null) receivingIterator = chatSync.beginReceive(Empty.newBuilder().build());
    try {
        if (receivingIterator.hasNext()) {
            ChatMessage message = receivingIterator.next();
            lockedQueue.Put(message);
            message.
        }
    } catch (io.grpc.StatusRuntimeException e) {
        receivingIterator = chatSync.beginReceive(Empty.newBuilder().build());
        Bukkit.getLogger().info("Chat Sync Connection Failed created new one!");
    }
}

} 所有线程都有相同的堆栈跟踪:

  java.lang.Thread.State: WAITING
  at jdk.internal.misc.Unsafe.park(Unsafe.java:-1)
  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:211)
  at io.grpc.stub.ClientCalls$ThreadlessExecutor.waitAndDrain(ClientCalls.java:731)
  at io.grpc.stub.ClientCalls$BlockingResponseStream.waitForNext(ClientCalls.java:622)
  at io.grpc.stub.ClientCalls$BlockingResponseStream.hasNext(ClientCalls.java:643)
  at HausSheepPlugin.GRPCMessageReceiver.run(GRPCMessageReceiver.java:26)
  at org.bukkit.craftbukkit.v1_16_R2.scheduler.CraftTask.run(CraftTask.java:81)
  at org.bukkit.craftbukkit.v1_16_R2.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:54)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
  at java.lang.Thread.run(Thread.java:832)

这是我的问题还是 GRPC 的问题?

【问题讨论】:

  • 看起来这是一个流式 RPC。流是否从服务器正确关闭?如果没有,您将有无数个线程都在等待它们的流结束。
  • 系统设置为Server可以向Client推送消息,而不是Client不断拉取消息。因此,只有在连接中断/服务器或客户端关闭时,服务器才会关闭流。
  • 那么您运行了多少个 RPC? run() 预计只会发生一次还是多次?
  • 运行每秒执行两次。第一次调用run() 时调用beginReceive 方法,当hasNext() 函数抛出io.grpc.StatusRuntimeException 时,这意味着连接出现故障。我已经检查过连接不会在每次Run() 执行时重新建立。
  • 你能说明run()是如何被执行的吗? receivingIterator 存储在哪里?

标签: java minecraft grpc-java


【解决方案1】:

hasNext() 一直等到元素到达或流关闭。

如果一个元素还没有到达,它会一直等待直到另一个元素到达。当许多调用都这样做时,您等待的线程比元素多,因此线程不断堆积。

因此,或多或少:您不应该以这种方式构建您的流接收。要么使用异步 API 和 StreamObserver——这似乎符合你的代码需求——要么让 run() 使用整个迭代器,而不是尝试只使用一个元素。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多