远程执行时出现 Hazelcast OperationTimeoutException

Hazelcast OperationTimeoutException on remote execution

我是 运行 AWS 中版本为 3.6.6 的 5 节点 Hazelcast 集群。 我将它用作工作负载分配器并且我正在使用

IExecutorService
<T> void submit(Runnable  task,
              MemberSelector memberSelector,
              ExecutionCallback<T> callback)

API 对我选择的成员执行任务。我不使用基于分区的平衡,因为不同的分区会有不同的权重。

在我启动集群后,它运行了好几天,然后提交成员开始收到 OperationTimeoutException。一旦开始,所有成员都开始收到此超时,并且它偶尔会发生,可能会在短时间内一切正常,然后此异常再次开始发生。目标成员确实在不到一秒的时间内收到任务并正确执行。 异常本身如下所示:

July 3rd 2019, 10:54:01 UTC:

No response for 560000 ms. Aborting invocation! Invocation{serviceName='hz:impl:executorService', op=com.hazelcast.executor.impl.operations.MemberCallableTaskOperation{identityHash=1179024466, serviceName='hz:impl:executorService', partitionId=-1, replicaIndex=0, callId=684145, invocationTime=1562150679963 (Wed Jul 03 10:44:39 UTC 2019), waitTimeout=-1, callTimeout=500000, name=exec_service_3}, partitionId=-1, replicaIndex=0, tryCount=250, tryPauseMillis=500, invokeCount=1, callTimeout=500000, target=Address[x.x.x.x]:5701, backupsExpected=0, backupsCompleted=0, connection=Connection [/x.x.x.x:5701 -> /x.x.x.x:35360], endpoint=Address[x.x.x.x]:5701, alive=true, type=MEMBER} No response has been received! backups-expected:0 backups-completed: 0, execution took: 3445 milliseconds

堆栈跟踪:

at com.hazelcast.spi.impl.operationservice.impl.Invocation.newOperationTimeoutException(Invocation.java:536) ~[anodot-arnorld-1.0-SNAPSHOT.jar:na]
    at com.hazelcast.spi.impl.operationservice.impl.IsStillRunningService$IsOperationStillRunningCallback.setOperationTimeout(IsStillRunningService.java:241)
    at com.hazelcast.spi.impl.operationservice.impl.IsStillRunningService$IsOperationStillRunningCallback.onResponse(IsStillRunningService.java:229)
    at com.hazelcast.spi.impl.operationservice.impl.InvocationFuture.run(InvocationFuture.java:127)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
    at com.hazelcast.util.executor.HazelcastManagedThread.executeRun(HazelcastManagedThread.java:76) [anodot-arnorld-1.0-SNAPSHOT.jar:na]
    at com.hazelcast.util.executor.HazelcastManagedThread.run(HazelcastManagedThread.java:92)
    at ------ End remote and begin local stack-trace ------.(Unknown Source) ~[na:na]
    ... 8 frames truncated

异常发生的时间很奇怪:

July 3rd 2019, 10:53:57.956 - task submitted for execution by sending instance
July 3rd 2019, 10:53:58.024 - execution starts on target instance
July 3rd 2019, 10:54:01.391 - the sending instance receives the exception

在我的日志中,我看到超时发生在任务提交后不久,并且异常的 "execution took:" 部分非常精确,实际上在引用的情况下自任务发送到执行时间约为 3.5 秒。另一方面,引用案例中的 "invocationTime",(Wed Jul 03 10:44:39 UTC 2019)大约是过去 10 分钟,甚至在作业实际提交执行之前(2019 年 7 月 3 日,10:53:57 UTC)

我已经看到此异常归因于长时间的 GC 暂停,但由于我一直在监视 GC,所以我很确定情况并非如此。此外,集群成员之间的网络看起来很活跃,延迟很低。

根据我在 Hazelcast 代码中看到的内容,"invocationTime" 取自 "clusterClock" 而不是直接取自系统时间,这表明由于某种原因集群时钟为 10 分钟关闭,但我不明白为什么会这样。集群非常繁忙,但当此异常开始发生时,我没有看到任何异常的负载激增。 当我关闭整个集群然后重新启动时,问题就消失了。 我计划在 clusterTime 上添加监控以查看它何时开始漂移,但它仍然无法解释为什么会发生这种情况。 有什么想法吗?

更新: 简而言之,集群时间随时间从系统时间漂移,一旦差距足够大,任务就会开始失败并出现超时异常。 详情:https://github.com/hazelcast/hazelcast/issues/15339

最后,通过将 Hazelcast 版本升级到 3.12.11 解决了这个问题(4.x.x 破坏了太多东西),看起来集群时间的管理方式对 GC 暂停不敏感。一些 API 损坏了,需要在代码中进行调整,没有什么太严重的。请注意,3.6.6 与 3.12.11 不兼容,因此无法进行滚动集群升级。我们做了一个完整的集群重启,幸运的是,这是可能的。