如何在单独的 docker Hazelcast 节点(应用程序中嵌入的主节点)禁用数据反序列化过程

How to disable deserialization process of data at separate docker Hazelcast nodes (main nodes embedded within app)

您好,提前致谢!

问题简而言之:

当为带有嵌入式 Hazelcast 的应用程序的所有项目模型使用自定义单个序列化程序时,如何在不为“hazelcast/hazelcast”设置此全局序列化程序的情况下使用“hazelcast/hazelcast”docker 图像?或者说没办法的原因。

更多:

我将在 Docker Swarm 中使用“hazelcast/hazelcast”docker 图像,只是为了在重新启动所有嵌入了 hazelcast 的应用程序时不会丢失数据。对于所有其他情况,使用应用程序内置的实例。因此,与 hazelcast 数据的所有直接通信只能通过嵌入到应用程序中的 Hazelcast 实例进行。

我使用 ReplicatedMap 和 ISet 结构。 对于 ReplicatedMap,我设置了“in-memory-format: BINARY”。 此外,我仅为应用程序设置自定义全局序列化程序 - 我需要一个序列化程序来处理我所有的项目类型,并使用我的自定义逻辑来确定实际 *.class 以反序列化 in.

我在“hazelcast/hazelcast”容器日志中看到以下错误:

2020-11-03 00:41:50,180 [ERROR] [hz.pedantic_maxwell.partition-operation.thread-4] [c.h.s.i.o.i.OperationRunnerImpl]: [192.168.1.103]:5700 [dev] [4.0.3] There is no suitable de-serializer for type 1. This exception is likely caused by differences in the serialization configuration between members or between clients and members.
com.hazelcast.nio.serialization.HazelcastSerializationException: There is no suitable de-serializer for type 1. This exception is likely caused by differences in the serialization configuration between members or between clients and members.
        at com.hazelcast.internal.serialization.impl.AbstractSerializationService.newHazelcastSerializationException(AbstractSerializationService.java:254) ~[hazelcast-all-4.0.3.jar:4.0.3]
        at com.hazelcast.internal.serialization.impl.AbstractSerializationService.readObject(AbstractSerializationService.java:280) ~[hazelcast-all-4.0.3.jar:4.0.3]
        at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataInput.readObject(ByteArrayObjectDataInput.java:567) ~[hazelcast-all-4.0.3.jar:4.0.3]
        at com.hazelcast.internal.nio.IOUtil.readObject(IOUtil.java:141) ~[hazelcast-all-4.0.3.jar:4.0.3]
        at com.hazelcast.replicatedmap.impl.operation.VersionResponsePair.readData(VersionResponsePair.java:58) ~[hazelcast-all-4.0.3.jar:4.0.3]
        at com.hazelcast.replicatedmap.impl.operation.ReplicateUpdateOperation.readInternal(ReplicateUpdateOperation.java:109) ~[hazelcast-all-4.0.3.jar:4.0.3]
        at com.hazelcast.spi.impl.operationservice.Operation.readData(Operation.java:750) ~[hazelcast-all-4.0.3.jar:4.0.3]
        at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.readInternal(DataSerializableSerializer.java:160) ~[hazelcast-all-4.0.3.jar:4.0.3]
        at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.read(DataSerializableSerializer.java:106) ~[hazelcast-all-4.0.3.jar:4.0.3]
        at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.read(DataSerializableSerializer.java:51) ~[hazelcast-all-4.0.3.jar:4.0.3]
        at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.read(StreamSerializerAdapter.java:44) ~[hazelcast-all-4.0.3.jar:4.0.3]
        at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toObject(AbstractSerializationService.java:203) ~[hazelcast-all-4.0.3.jar:4.0.3]
        at com.hazelcast.spi.impl.NodeEngineImpl.toObject(NodeEngineImpl.java:339) ~[hazelcast-all-4.0.3.jar:4.0.3]
        at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:407) [hazelcast-all-4.0.3.jar:4.0.3]
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:166) [hazelcast-all-4.0.3.jar:4.0.3]
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:136) [hazelcast-all-4.0.3.jar:4.0.3]
        at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.run(OperationThread.java:123) [hazelcast-all-4.0.3.jar:4.0.3]

但我想不通原因。所有节点都是成员,并且只有应用程序嵌入式 Hazelcast 节点从 ReplicatedMap 和 ISet 写入和获取数据。 我也试过设置以下设置:

hazelcast:
  serialization:
    check-class-def-errors: false

所以,我预计没有理由在“hazelcast/hazelcast”docker 个节点内进行数据反序列化。我哪里错了?

此外,在我的自定义序列化程序日志中,我惊讶地看到“HazelcastException.class、ClusterState.class、IllegalArgumentException.class”类型。我试图修复它,使用 hazelcasts 'JavaDefaultSerializers.JavaSerializer.class' 为此类型添加自定义序列化程序。 在这一步的某个地方,我以为我做错了什么......:) 我最后添加的类型是 IllegalArgumentException 和 Exception finally。现在正在等待结果...

也许我遗漏了一些设置。但如果可能的话,我不想创建自己的 docker 图像,也不想为它设置一个全局反序列化器。或者至少弄清楚为什么这是不可能的。

如果有帮助,也许我可以不用 ISet。不过能用当然更好

使用 ReplicatedMap 是使用 Hazelcast 的原因。 我尝试它是为了加快 'user_api' 类服务的响应速度,当 docker 集群中有几个单独的服务在那里写入数据并且整个实际数据可以存储在一台机器中时(~1- 2GB).

更新 04.11.20 21:48:

我在本地测试了应用程序(带有嵌入式 Hazelcast)启动两次和一个单独的 Hazelcast 的情况。现在似乎一切正常。所以,最后我在反序列化中发现了类型:PartitionMigratingException, CallerNotMemberException, RetryableHazelcastException, WrongTargetException and ClusterState

似乎使用 hazelcasts 的 JavaDefaultSerializers.JavaSerializer.class 为类型 Exception.class and ClusterState.class 指定自定义序列化程序解决了这个问题。但这对于 ClusterState.class 情况来说尤其奇怪。

最后一个很简单 enum,它表明我最终需要添加来自 'com.hazelcast' 的所有 class 以避免序列化问题...

可能会回答我的问题:

当使用单独的 Hazelcast 实例时,只是为了在重新启动所有嵌入了 hazelcast 的应用程序时不会丢失数据。当全局反序列化器用于应用程序端的所有项目类型时,您需要:

  1. hazelcast.serialization.check-class-def-errors: false 至少对于未嵌入的 Hazelcast
  2. 确保所有结构设置为in-memory-format: BINARY
  3. 在应用程序端,您需要使用 JavaDefaultSerializers.JavaSerializer.class 为 Exception.class 和包 'com.hazelcast'
  4. 中的其他类型添加自定义反序列化器

使用一段时间后会更新资料

Serialization/Deserialization 是从分布式系统存储和检索数据的过程的一部分。当数据写入具有默认配置的任何数据结构时,数据将被序列化。当查询数据时,它在应用程序端被反序列化。无论部署策略如何,都会发生这种情况 - client/server 或嵌入到应用程序中,Docker 或没有 Docker。

要修复异常,您需要将域对象或正在写入服务器的对象的 class 定义放置在服务器以及应用程序的 class 路径上。

注意:如果您使用的是 IMap,那么您可以选择在服务器上以反序列化形式存储数据,以加快计算速度或 predicate/queries 执行速度,但这不是您想要的。

无论应用是嵌入式还是 client/server,反序列化都会发生。原因 - 存储在 Hazelcast 服务器上的数据不仅适用于本地应用程序实例,还适用于连接到此集群的任何应用程序。嵌入式模式只是与集群对话的另一种方式,它不会影响数据操作的执行方式;除非您手动将 in-memory-format 配置为其他内容,这将再次应用于所有服务器。

旁注:您还可以使用客户端 API 将应用程序与合适的客户端库连接起来,从而与嵌入式模式集群进行连接和通信。