Java 如何检查Kafka服务器是否正在运行?

Java 如何检查Kafka服务器是否正在运行?,java,apache-kafka,kafka-producer-api,Java,Apache Kafka,Kafka Producer Api,我想在开始生产和消费作业之前确保kafka服务器是否正在运行。它在windows环境中,下面是我的kafka服务器在eclipse中的代码 Properties properties = new Properties(); properties.setProperty("broker.id", "1"); properties.setProperty("port", "9092"); properties.setPr

我想在开始生产和消费作业之前确保kafka服务器是否正在运行。它在windows环境中,下面是我的kafka服务器在eclipse中的代码

Properties properties = new Properties();
properties.setProperty("broker.id", "1");
properties.setProperty("port", "9092");
properties.setProperty("log.dirs", "D://workspace//");
properties.setProperty("zookeeper.connect", "localhost:2181"); 

Option<String> option = Option.empty();
KafkaConfig config = new KafkaConfig(properties);       
KafkaServer kafka = new KafkaServer(config, new CurrentTime(), option);
kafka.startup();
Properties属性=新属性();
properties.setProperty(“broker.id”,“1”);
属性。setProperty(“端口”,“9092”);
properties.setProperty(“log.dirs”,“D://workspace/”;
setProperty(“zookeeper.connect”,“localhost:2181”);
Option=Option.empty();
Kafkanconfig config=新的Kafkanconfig(属性);
KafkaServer kafka=新的KafkaServer(配置,new CurrentTime(),选项);
kafka.startup();

在本例中,
if(kafka!=null)
是不够的,因为它总是正确的。那么,有没有办法知道我的卡夫卡服务器正在运行并准备好供制作人使用呢。我有必要对此进行检查,因为它会导致一些起始数据包丢失。

所有卡夫卡代理必须分配一个
代理.id
。启动时,代理将在Zookeeper中创建一个临时节点,路径为
/broker/ids/$id
。由于该节点是短暂的,它将在代理断开连接(例如通过关闭)后立即删除

您可以查看临时代理节点的列表,如下所示:

echo dump | nc localhost 2181 | grep代理

ZooKeeper客户端界面公开了许多命令<代码>转储列出集群的所有会话和临时节点

注意,以上假设:

  • 您正在
    localhost
    上的默认端口(
    2181
    )上运行ZooKeeper,而
    localhost
    是集群的领导者
  • 您的
    zookeeper.connect
    Kafka配置没有为您的Kafka集群指定chroot-env,即它只是
    host:port
    而不是
    host:port/path

保罗的回答很好,从经纪人的角度来看,这实际上是卡夫卡和Zk如何合作的

我想说,检查Kafka服务器是否正在运行的另一个简单选项是创建一个指向cluste的简单Kafka消费者,并尝试一些操作,例如,listTopics()。如果kafka服务器未运行,您将得到一个TimeoutException,然后您可以使用
try catch
语句

  def validateKafkaConnection(kafkaParams : mutable.Map[String, Object]) : Unit = {
    val props = new Properties()
    props.put("bootstrap.servers", kafkaParams.get("bootstrap.servers").get.toString)
    props.put("group.id", kafkaParams.get("group.id").get.toString)
    props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer")
    props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer")
    val simpleConsumer = new KafkaConsumer[String, String](props)
    simpleConsumer.listTopics()
  }
好的选择是在开始生成或使用消息之前使用如下所示

private static final int ADMIN_CLIENT_TIMEOUT_MS = 5000;           
 try (AdminClient client = AdminClient.create(properties)) {
            client.listTopics(new ListTopicsOptions().timeoutMs(ADMIN_CLIENT_TIMEOUT_MS)).listings().get();
        } catch (ExecutionException ex) {
            LOG.error("Kafka is not available, timed out after {} ms", ADMIN_CLIENT_TIMEOUT_MS);
            return;
        }
我使用了api

Properties属性=新属性();
properties.put(“bootstrap.servers”,“localhost:9092”);
properties.put(“connections.max.idle.ms”,10000);
properties.put(“request.timeout.ms”,5000);
try(AdminClient=KafkaAdminClient.create(属性))
{
ListTopicsResult topics=client.listTopics();
Set name=topics.names().get();
if(names.isEmpty())
{
//案例:如果没有找到主题。
}
返回true;
}
捕获(中断异常|执行异常e)
{
//卡夫卡不可用
}

如果服务器正在运行,您可以使用下面的代码检查可用的代理

import org.I0Itec.zkclient.ZkClient;
     public static boolean isBrokerRunning(){
        boolean flag = false;
        ZkClient zkClient = new ZkClient(endpoint.getZookeeperConnect(), 10000);//, kafka.utils.ZKStringSerializer$.MODULE$);
        if(zkClient!=null){
            int brokersCount = zkClient.countChildren(ZkUtils.BrokerIdsPath());
            if(brokersCount > 0){
                logger.info("Following Broker(s) {} is/are available on Zookeeper.",zkClient.getChildren(ZkUtils.BrokerIdsPath()));
                flag = true;    
            }
            else{
                logger.error("ERROR:No Broker is available on Zookeeper.");
            }
            zkClient.close();

        }
        return flag;
    }

我在合流的卡夫卡中发现了一个事件
OnError

consumer.OnError += Consumer_OnError;

 private void Consumer_OnError(object sender, Error e)
    {
        Debug.Log("connection error: "+ e.Reason);
        ConsumerConnectionError(e);
    }
及其代码文档:

    //
    // Summary:
    //     Raised on critical errors, e.g. connection failures or all brokers down. Note
    //     that the client will try to automatically recover from errors - these errors
    //     should be seen as informational rather than catastrophic
    //
    // Remarks:
    //     Executes on the same thread as every other Consumer event handler (except OnLog
    //     which may be called from an arbitrary thread).
    public event EventHandler<Error> OnError;
//
//总结:
//在出现严重错误时引发,例如连接失败或所有代理关闭。注
//客户端将尝试从错误中自动恢复-这些错误
//应该被视为信息性的,而不是灾难性的
//
//备注:
//与其他每个使用者事件处理程序(OnLog除外)在同一线程上执行
//可以从任意线程调用)。
公共事件事件处理程序OnError;

对于Linux,“ps aux|grep kafka”查看结果中是否显示kafka属性。例如/path/to/kafka/server.properties

首先需要创建AdminClientbean:

 @Bean
 public AdminClient adminClient(){
   Map<String, Object> configs = new HashMap<>();
   configs.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG,
   StringUtils.arrayToCommaDelimitedString(new Object[]{"your bootstrap server address}));
   return AdminClient.create(configs);
 }
@Bean
公共AdminClient AdminClient(){
Map configs=new HashMap();
configs.put(AdminClientConfig.BOOTSTRAP\u SERVERS\u CONFIG,
arrayToCommaDelimitedString(新对象[]{“您的引导服务器地址}”);
返回AdminClient.create(配置);
}
然后,您可以使用以下脚本:

while (true) {
   Map<String, ConsumerGroupDescription> groupDescriptionMap =
         adminClient.describeConsumerGroups(Collections.singletonList(groupId))
         .all()
         .get(10, TimeUnit.SECONDS);

   ConsumerGroupDescription consumerGroupDescription = groupDescriptionMap.get(groupId);

   log.debug("Kafka consumer group ({}) state: {}",
                groupId,
                consumerGroupDescription.state());

   if (consumerGroupDescription.state().equals(ConsumerGroupState.STABLE)) {
        boolean isReady = true;
        for (MemberDescription member : consumerGroupDescription.members()) {
            if (member.assignment() == null || member.assignment().topicPartitions().isEmpty()) {
            isReady = false;
            }
        }

        if (isReady) {
            break;
           }
        }

        log.debug("Kafka consumer group ({}) is not ready. Waiting...", groupId);
        TimeUnit.SECONDS.sleep(1);
}
while(true){
映射组描述映射=
adminClient.describeConsumerGroups(Collections.singletonList(groupId))
.all()
.get(10,时间单位秒);
ConsumerGroupDescription ConsumerGroupDescription=groupDescriptionMap.get(groupId);
debug(“Kafka使用者组({})状态:{}”,
groupId,
consumerGroupDescription.state());
if(consumerGroupDescription.state().equals(ConsumerGroupState.STABLE)){
布尔值isReady=true;
对于(MemberDescription成员:consumerGroupDescription.members()){
if(member.assignment()==null | | member.assignment().topicPartitions().isEmpty()){
isReady=false;
}
}
如果(isReady){
打破
}
}
log.debug(“Kafka使用者组({})未就绪。正在等待…”,groupId);
时间单位。秒。睡眠(1);
}

此脚本将每秒检查使用者组的状态,直到状态稳定为止。因为所有分配给主题分区的使用者都可以断定服务器正在运行并准备就绪。

您可以在计算机上安装Kafkacat工具

例如,在Ubuntu上,您可以使用

apt获取并安装kafkacat
安装kafkacat后,可以使用以下命令连接它

kafkacat-b:-t测试主题
  • 用机器ip替换
  • 可以由运行kafka的端口替换。通常为9092

运行上述命令后,如果kafkacat能够建立连接,则表示kafka已启动并正在运行

我只启动了zookeeper而不是kafka,然后
while (true) {
   Map<String, ConsumerGroupDescription> groupDescriptionMap =
         adminClient.describeConsumerGroups(Collections.singletonList(groupId))
         .all()
         .get(10, TimeUnit.SECONDS);

   ConsumerGroupDescription consumerGroupDescription = groupDescriptionMap.get(groupId);

   log.debug("Kafka consumer group ({}) state: {}",
                groupId,
                consumerGroupDescription.state());

   if (consumerGroupDescription.state().equals(ConsumerGroupState.STABLE)) {
        boolean isReady = true;
        for (MemberDescription member : consumerGroupDescription.members()) {
            if (member.assignment() == null || member.assignment().topicPartitions().isEmpty()) {
            isReady = false;
            }
        }

        if (isReady) {
            break;
           }
        }

        log.debug("Kafka consumer group ({}) is not ready. Waiting...", groupId);
        TimeUnit.SECONDS.sleep(1);
}