【问题标题】:Discovery problems of multiple Hazelcast instances using Kubernetes dns add-on使用 Kubernetes dns 插件发现多个 Hazelcast 实例的问题
【发布时间】:2018-04-20 01:53:25
【问题描述】:

我使用 JHipster 创建了一个单体应用程序,我想在 GCP Kubernetes Engine 集群上运行它的多个副本。

由于我想在副本(甚至该集群上的服务)之间共享数据,我决定使用内置的 Hazelcast 缓存,但我不想使用推荐的 Eureka 发现客户端K8 dns-discovery 插件。

所以我已经添加到我的 pom.xml 中:

<dependency>
    <groupId>com.hazelcast</groupId>
    <artifactId>hazelcast-kubernetes</artifactId>
    <version>1.1.0</version>
</dependency>

并使用生成的 CacheConfiguration.java 文件来支持 hazelcast-kubernetes 配置(基于他们的github repo):

@Bean
public HazelcastInstance hazelcastInstance(JHipsterProperties jHipsterProperties) {
    log.debug("Configuring Hazelcast");
    HazelcastInstance hazelCastInstance = Hazelcast.getHazelcastInstanceByName("hazelcastK8");
    if (hazelCastInstance != null) {
        log.debug("Hazelcast already initialized");
        return hazelCastInstance;
    }
    Config config = new Config();
    config.setInstanceName("hazelcastK8");
    config.getNetworkConfig().setPort(5701);
    config.getNetworkConfig().setPortAutoIncrement(true);

    config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);
    config.getNetworkConfig().getJoin().getTcpIpConfig().setEnabled(false);

    if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
        System.setProperty("hazelcast.local.localAddress", "127.0.0.1");
        config.getNetworkConfig().getJoin().getAwsConfig().setEnabled(false);
    } else { // In production we want to use hazelcast k8's dns discovery service
        log.info("Configuring hazelcast DNS discovery by K8");

        DiscoveryStrategyConfig strategyConfig =
            new DiscoveryStrategyConfig(
                new HazelcastKubernetesDiscoveryStrategyFactory()
            );

        // Default namespace
        strategyConfig.addProperty("service-dns", "hazelcastk8.default.svc.cluster.local");
        strategyConfig.addProperty("service-dns-timeout", 10);

        config.getNetworkConfig().getJoin().getDiscoveryConfig().addDiscoveryStrategyConfig(strategyConfig);
    }

    config.getMapConfigs().put("default", initializeDefaultMapConfig());
    config.setManagementCenterConfig(initializeDefaultManagementCenterConfig(jHipsterProperties));
    config.getMapConfigs().put("com.company.distributed.domain.*", initializeDomainMapConfig(jHipsterProperties));

    return Hazelcast.newHazelcastInstance(config);
}

为了检查数据网格是否按预期工作,我编写了一个简单的计划任务,用于打印 atomic-long 的当前值:

@Service
@Profile(JHipsterConstants.SPRING_PROFILE_PRODUCTION)
public class FetchHazelcastClusterSequence {

    private final HazelcastInstance hazelcastInstance;

    private static final Logger log = LoggerFactory.getLogger(FetchHazelcastClusterSequence.class);

    public FetchHazelcastClusterSequence(HazelcastInstance hazelcastInstance) {
        this.hazelcastInstance = hazelcastInstance;
    }

    @Timed
    @Scheduled(fixedDelay = 5000)
    public void start() {
        log.info("Fetching cluster sequence, the current value is: {}", this.hazelcastInstance.getAtomicLong("sequence").getAndIncrement());
    }
}

但是当我启动应用程序时,默认配置为 3 个副本,创建了 3 个 pod,但每个 pod 日志显示好像它是集群中的唯一成员,因此打印相同的“序列”值”。

我是否缺少一些配置?

【问题讨论】:

    标签: dns kubernetes google-cloud-platform jhipster hazelcast


    【解决方案1】:

    @lior-ziv,您的配置缺少一个重要的配置参数:

    1 - 使用SPRING_PROFILE_DEVELOPMENT 配置文件时,您没有启用任何发现机制。您需要启用TCP-IP 发现,否则所有成员将启动一个单节点集群。

    2 - 使用 SPRING_PROFILE_PRODUCTION 配置文件时,您有 Kubernetes 发现插件,但您根本没有启用发现。这就是为什么每次启动新实例时它也会创建单个成员集群的原因。

    正确的配置应该是这样的:

    //Move this like outside of if block since it'll be disabled for both cases.
    config.getNetworkConfig().getJoin().getAwsConfig().setEnabled(false);
    
    if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
        config.getNetworkConfig().getJoin().getTcpIpConfig().setEnabled(true);
        config.getNetworkConfig().getJoin().getTcpIpConfig().addMember("127.0.0.1");`
    } else {
        // In production we want to use hazelcast k8's dns discovery service
        System.setProperty("hazelcast.discovery.enabled", "true");
        log.info("Configuring hazelcast DNS discovery by K8");
    
        DiscoveryStrategyConfig strategyConfig =
            new DiscoveryStrategyConfig(
                new HazelcastKubernetesDiscoveryStrategyFactory()
            );
    
        // Default namespace
        strategyConfig.addProperty("service-dns", "hazelcastk8.default.svc.cluster.local");
        strategyConfig.addProperty("service-dns-timeout", 10);
    
        config.getNetworkConfig().getJoin().getDiscoveryConfig().addDiscoveryStrategyConfig(strategyConfig);
    }
    

    【讨论】:

    • 感谢@gokhan-oner,我现在可以在启用发现后发现每个 pod 都找到自己,并且正在调用 5701 端口(hazelcast 端口)上的 cluster-ip,但经过由于超时,它返回SocketException。你认为我在 yml 文件中可能缺少一些配置吗?
    • @LiorZiv,你能在异常之前/之后分享完整的堆栈跟踪和一些日志行吗?
    猜你喜欢
    • 2022-12-07
    • 1970-01-01
    • 2017-08-05
    • 2017-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多