如何在不解析日志文件的情况下获取Kafka连接状态?能够对"在身份验证期间终止的节点连接采取措施。"

时间:2018-06-04 06:27:39

标签: java apache-kafka kafka-consumer-api spring-kafka

使用不正确的凭据进行身份验证时,我在身份验证期间收到了以下预期消息。

  

[Consumer clientId = consumer-1,groupId = xxx]与节点-1的连接   验证期间终止。这可能表明了这一点   由于凭据无效,身份验证失败。

这一切都很好,但是现在我只能在日志文件中找到这些信息,而我想对这条消息采取行动。

我还查看了此消息源自的Kafka源代码:

(在1.1中)https://github.com/apache/kafka/blob/1.1/clients/src/main/java/org/apache/kafka/clients/NetworkClient.java (或在主干中)https://github.com/apache/kafka/blob/trunk/clients/src/main/java/org/apache/kafka/clients/NetworkClient.java

有一些像这样的代码:

switch (disconnectState.state()) {
            case AUTHENTICATION_FAILED:
                connectionStates.authenticationFailed(nodeId, now, disconnectState.exception());
                log.error("Connection to node {} failed authentication due to: {}", nodeId, disconnectState.exception().getMessage());
                break;
            case AUTHENTICATE:
                // This warning applies to older brokers which dont provide feedback on authentication failures
                log.warn("Connection to node {} terminated during authentication. This may indicate " +
                        "that authentication failed due to invalid credentials.", nodeId);
                break;

重要提示:我使用基于SASL_PLAIN的自定义模块覆盖Kafka中的身份验证机制,而我刚刚调试时,我在身份验证期间意识到此模块中出现了其他问题,导致了与此不同的异常模块,这意味着它触发了这个老年经纪人'代码路径。但是,我仍然希望对这个州采取一些行动。

我尝试过创建一个监听器,如下所示:

    final ContainerProperties containerProperties = new ContainerProperties("TEST_TOPIC");
    containerProperties.setAckMode(AbstractMessageListenerContainer.AckMode.MANUAL_IMMEDIATE);
    containerProperties.setMessageListener((AcknowledgingMessageListener<GenericRecord, GenericRecord>) (record, ack) -> logger.info("Got record on test topic"));
    KafkaMessageListenerContainer<GenericRecord, GenericRecord> container = new KafkaMessageListenerContainer<>(kafkaConsumerFactory, containerProperties);
    container.start();

但代码不会抛出任何身份验证异常,它只是在日志中继续打印上述消息。

我也尝试过创建一个简单的消费者,如下所示:

    Consumer<GenericRecord, GenericRecord> consumer = kafkaConsumerFactory.createConsumer();
    consumer.subscribe(Collections.singleton("BX_TEST_TOPIC"));
    try {
        ConsumerRecords<GenericRecord, GenericRecord> poll = consumer.poll(10);
    }
    catch (Exception e) {
        logger.info("Exception during polling", e);
    }

但是这段代码也没有抛出任何异常,它也只是在日志中继续打印消息。即使根据https://kafka.apache.org/10/javadoc/org/apache/kafka/clients/consumer/KafkaConsumer.html#poll-long-,poll方法可能会抛出AuthenticationException。这可能是因为年龄较大的经纪人&#39;消息类型,在源代码中仅在日志中显示警告。

那么,如果服务器没有返回认证异常但仍然无法登录,如何实际捕获任何AuthenticationException或以某种有意义的方式获取连接状态而不是解析日志?

请注意,当身份验证不是问题时会发生完全相同的问题,但其他问题会失败。例如,有时我的Kafka集群没有正确启动,在这种情况下,我收到此消息:

  

无法建立与节点-1的连接。经纪人可能不会   可用。

我也无法检查。相反,当客户端进入无限循环尝试连接时,日志会不断填写此消息。

1 个答案:

答案 0 :(得分:1)

您可以通过增加重试退避来减少循环。

您可以使用类似......

之类的内容来检查经纪人的状态
spring.kafka.producer.properties.retry.backoff.ms=1000
spring.kafka.producer.properties.max.block.ms=10000
spring.kafka.bootstrap-servers=localhost:9096

@Bean
public ApplicationRunner runner(ProducerFactory<?, ?> producerFactory) {
    return args -> {
        try (Producer<?, ?> producer = producerFactory.createProducer()) {
            producer.partitionsFor("foo");
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    };
}

org.apache.kafka.common.errors.TimeoutException: Failed to update metadata after 10000 ms.

我缩小了max.block.ms,因为它默认为60秒。