kubernetes 上的 Hazelcast 地图不同步

Hazelcast map on kubernetes not in sync

使用 hazelcast 编写一个基于 spring 的基于 kotlin 的应用程序我在部署到 kubernetes 时遇到问题。

对于 kubernetes 上的 hazelcast,我使用 DNS lookup mode 进行发现。 我有以下 hazelcast 配置:

hazelcast:
  network:
    join:
      multicast:
        enabled: false
      kubernetes:
        enabled: true
        service-dns: my-application-hs

以及以下 service.yaml 用于 kubernetes 部署:

apiVersion: v1
kind: Service
metadata:
  name: my-application

spec:
  type: ClusterIP
  selector:
    component: my-application
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: http
---
apiVersion: v1
kind: Service
metadata:
  name: my-application-hs

spec:
  type: ClusterIP
  clusterIP: None
  selector:
    component: my-application
  ports:
    - name: hazelcast
      port: 5701

hazelcast 贴图是这样使用的:

@Component
class CacheClientImplHazelcast(){

    private val hz: HazelcastInstance

    init{
        val serializer = SerializerConfig()
            .setTypeClass(MyDto::class.java)
            .setImplementation(MyDtoSerializer())
        val config = Config()
        config.serializationConfig.addSerializerConfig(serializer)
        hz = Hazelcast.newHazelcastInstance(config)
    }

    fun getAllData(): List<MyDto> {
        val map: IMap<String, MyDto> = hz.getMap("my-map")
        return map.values.toList()
    }

    fun putData(key:String, myDto: MyDto) {
        val map: IMap<String, MyDto> = hz.getMap("my-map")
        map.put(key, myDto)
    }

    override fun clear() {
        val map: IMap<String, MyDto> = hz.getMap("my-map")
        map.clear()
    }
}

当 运行在 kubernetes 上运行 3 个实例时,hazelcast 的日志总是显示 4 个条目,如下所示:

Members {size:4, ver:53} [
  Member [10.4.2.32]:5701 - c1e70d6f-a62d-4924-9815-36bb1f98f141
  Member [10.4.3.25]:5702 - be96c292-8847-4f56-ae32-f27f380d7c5b
  Member [10.4.2.32]:5702 - 6ca96bfd-eb74-4149-8630-a2488e76d97d
  Member [10.4.11.41]:5702 - 7e8b0bc9-ad2b-41eb-afbf-b7af9ed497bd this
] 

(附带问题 1:为什么我在这里看到的是 4 而不是 3?)

现在,即使成员似乎已连接(至少节点的日志显示所有相同的成员 uuid),当我在一个节点上写入数据时,它在其他节点上不可用。调用 getAllData 仅显示已放入该节点上的 hazelcast 映射中的数据。当我向各个节点(shell 上的 curl)发送请求时,我只看到一小部分数据。当我在 pod 的正常 url 上发送请求然后使用循环我得到不同节点的数据,这些数据不同步。

如果我 运行 在本地使用相同的应用程序 hazelcast.yaml:

hazelcast:
  network:
    join:
      multicast:
        enabled: false

然后一切正常,缓存似乎真的在本地 运行 跨不同服务器实例“同步”。对于此测试,我在不同的端口上启动应用程序。

然而奇怪的是,即使我在本地 运行 2 个实例,我从 hazelcast 看到的日志显示有 4 个成员:

Members {size:4, ver:4} [
    Member [192.168.68.106]:5701 - 01713c9f-7718-4ed4-b532-aaf62443c425
    Member [192.168.68.106]:5702 - 09921004-88ef-4fe5-9376-b88869fde2bc
    Member [192.168.68.106]:5703 - cea4b13f-d538-48f1-b0f2-6c53678c5823 this
    Member [192.168.68.106]:5704 - 44d84e70-5b68-4c69-a45b-fee39bd75554
]  

(附带问题2:为什么我只在本地启动了2个却看到4个成员?)

现在的主要问题是:为什么这个设置在 kubernetes 上不起作用?为什么每个节点都有一个与其他节点不同步的单独地图?

这里有一些可能相关但我无法确定问题的日志消息:

2022-04-19T12:29:31.414588357Z2022-04-19 12:29:31.414 INFO 1 --- [cached.thread-7] c.h.i.server.tcp.TcpServerConnector : [10.4.11.41]:5702 [dev] [5.1.1] Connecting to /10.4.3.25:5702, timeout: 10000, bind-any: true
2022-04-19T12:29:31.414806473Z2022-04-19 12:29:31.414 INFO 1 --- [.IO.thread-in-2] c.h.i.server.tcp.TcpServerConnection : [10.4.11.41]:5702 [dev] [5.1.1] Initialized new cluster connection between /10.4.11.41:5702 and /10.4.3.25:46475
2022-04-19T12:29:31.414905573Z2022-04-19 12:29:31.414 INFO 1 --- [cached.thread-4] c.h.i.server.tcp.TcpServerConnector : [10.4.11.41]:5702 [dev] [5.1.1] Connecting to /10.4.2.32:5702, timeout: 10000, bind-any: true
2022-04-19T12:29:31.416520854Z2022-04-19 12:29:31.416 INFO 1 --- [.IO.thread-in-0] c.h.i.server.tcp.TcpServerConnection : [10.4.3.25]:5702 [dev] [5.1.1] Initialized new cluster connection between /10.4.3.25:5702 and /10.4.11.41:40455
2022-04-19T12:29:31.416833551Z2022-04-19 12:29:31.416 INFO 1 --- [.IO.thread-in-1] c.h.i.server.tcp.TcpServerConnection : [10.4.2.32]:5702 [dev] [5.1.1] Initialized new cluster connection between /10.4.2.32:54433 and /10.4.11.41:5702
2022-04-19T12:29:31.417377114Z2022-04-19 12:29:31.417 INFO 1 --- [.IO.thread-in-0] c.h.i.server.tcp.TcpServerConnection : [10.4.11.41]:5702 [dev] [5.1.1] Initialized new cluster connection between /10.4.11.41:40455 and /10.4.3.25:5702
2022-04-19T12:29:31.417545174Z2022-04-19 12:29:31.417 INFO 1 --- [.IO.thread-in-2] c.h.i.server.tcp.TcpServerConnection : [10.4.2.32]:5702 [dev] [5.1.1] Initialized new cluster connection between /10.4.2.32:5702 and /10.4.11.41:53547
2022-04-19T12:29:31.418541840Z2022-04-19 12:29:31.418 INFO 1 --- [.IO.thread-in-1] c.h.i.server.tcp.TcpServerConnection : [10.4.11.41]:5702 [dev] [5.1.1] Initialized new cluster connection between /10.4.11.41:53547 and /10.4.2.32:5702
2022-04-19T12:29:31.419763311Z2022-04-19 12:29:31.419 INFO 1 --- [.IO.thread-in-2] c.h.i.server.tcp.TcpServerConnection : [10.4.3.25]:5702 [dev] [5.1.1] Initialized new cluster connection between /10.4.3.25:46475 and /10.4.11.41:5702
2022-04-19T12:29:31.676218042Z2022-04-19 12:29:31.675 INFO 1 --- [gulis.migration] c.h.i.partition.impl.MigrationManager : [10.4.2.32]:5701 [dev] [5.1.1] Repartitioning cluster data. Migration tasks count: 271
                                                                                                                                                   

这里有两个问题,但只有一个问题。

  1. 为什么额外的实例

Spring(引导)如果找到 Hazelcast 配置文件但没有找到 HazelcastInstance @Bean,将为您创建一个 Hazelcast 实例。您可以通过排除 HazelcastAutoConfiguration.class 或将您在组件 class 中创建的实例作为 @Bean 返回来修复。

  1. 为什么 kubernetes 上的数据同步问题

每个 pod 意外地有 2 个 Hazelcast 节点,一个在 5701 上,一个在 5702 上。但是您的 ClusterIP 只列出了 5701。从外部无法访问 pod 中的某些实例。当您解决第一个问题时,这将消失。