kafka安装与测试

kafka安装:
很简单这里就不说了。
启动kafka服务器:
1.启动zookeeper:
使用kafka自带zookeeper
在kafka安装目录下运行命令:

bin/zookeeper-server-start.sh config/zookeeper.properties 

(默认zookeeper绑定在2181端口上)

2.启动kafka broker

bin/kafka-server-start.sh config/server.properties 

3.创建一个Topic名字为Husin

bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 \
> --partitions 1 --topic Husin

4.验证topic是否创建成功

bin/kafka-topics.sh --list --zookeeper localhost:2181

5.启动一个Producer并发送消息

bin/kafka-console-producer.sh --broker-list localhost:9092 --topic Husin

(注意,通信的端口是在9092不是2181)

6.启动一个consumer接收消息

bin/kafka-console-consumer.sh --zookeeper localhost:2181 --topic Husin --from-beginning

(注意,启动的通信服务端口是2181不是9092)

7.关闭zookeeper和kafka

停止kafka
bin/kafka-server-stop.sh
停止zookeeper
bin/zookeeper-server-stop.sh

(ps:不知道为什么服务端口不统一,可能是配置的问题,定义其他的端口号是无法接收的,而且,producer必须是9092,consumer必须是2181,奇怪了!)

扫描二维码关注公众号,回复: 2400830 查看本文章

更新:
没错的确是这样,producer的端口是在9092,consumer的端口必须是在2181,这是分布式消息系统,不需要producer和consumer端口对应的.
实际原因是kafka是生产者,zookeeper是消费者.

下面这篇文章介绍了kafka相关的命令操作,值得学习:
http://www.cnblogs.com/qizhelongdeyang/p/7354315.html

Java下使用kafka API

这是一个单线程发送接收的kafka实例:

producer端代码:

public class kafkaProducer
{
    public static void main(String[] args){
        Properties props = new Properties();
        props.put("bootstrap.servers", "localhost:9092");
        props.put("acks", "all");
        props.put("retries", 0);
        props.put("batch.size", 16384);
        props.put("linger.ms", 1);
        props.put("buffer.memory", 33554432);
        props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

        Producer<String, String> producer = new KafkaProducer<>(props);
        for(int i = 0; i<100; i++) {
            System.out.println(i);
            producer.send(new ProducerRecord<>("test", Integer.toString(i), Integer.toString(i)));
        }
    }
}

consumer端代码:

public class kafkaConsumer {

        public static void main(String[] args) {
            Properties props = new Properties();
            props.put("bootstrap.servers", "localhost:2181");
            props.put("group.id", "test-consumer-group");
            props.put("enable.auto.commit", "true");
            props.put("auto.commit.interval.ms", "1000");
            props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
            props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
            KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
            consumer.subscribe(Arrays.asList("test", "test"));
            while(true) {
                ConsumerRecords<String, String> records = consumer.poll(100);
                for (ConsumerRecord<String, String> record: records){
                    System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value());
                }
            }
        }
}

Maven工程依赖:

    <!--这是kafka依赖-->
    <dependency>
      <groupId>org.apache.kafka</groupId>
      <artifactId>kafka_2.11</artifactId>
      <version>1.0.0</version>
    </dependency>

kafka Java Api使用遇到的坑:
producer能正常发送消息 , 但是consumer接受不到消息。换了一个版本可以正常发送消息 , Java producer发送的消息能被控制台开启的consumer接收到,但是java consumer一直接收不到消息。
原因:
代码本身没有问题,问题出在consumer的配置上。
consumer没有配置
props.put(“auto.offset.reset”, “earliest”);
网上大多数的demo都没有这个配置,真不知道他们的结果从哪来的。

//该配置的解释
该参数表示当前groupId下的消费者,在ZK中没有offset值时(比新的groupid,或者是zk数据被清空),consumer应该从哪个offset开始消费,第二个参数若是latest则表示接受接收最大的offser(即最新消息),earliest表示最小offset,即从topic的开始位置消费所有消息,最好设置为earliest,这样新的分组才能从最开始进行处理。

kafka的消息发送机制及其原理:
每当用户往topic发送数据时,数据会被hash到不同的partition,这些partition位于不同的集群节点上(也就是说发送的消息是被分布式存储在不同机器上的),所以每个消息都会被记录一个offset消息号,随着消息的增加offset也会增加.消费者就是通过这个offset号去查询读取这个消息的。
消息会均匀的发送到不同的partition中,也就是机器的存储压力是均匀的。
消费者有组的概念,首先每一个组都能完全的接受到topic的全部消息,但是组内会竞争消费消息,比如topic有10条消息,有A B两个消费组,AB组都能接收到这10条消息,但是并不是AB组内所有消费者都能接收到这10条消息。

kafka java 配置详解
生产者:
* bootstrap.servers:Kafka集群连接串,可以由多个host:port组成。
* acks:broker消息确认的模式,有三种:
0:不进行消息接收确认,即Client端发送完成后不会等待Broker的确认;
1:由Leader确认,Leader接收到消息后会立即返回确认信息;
all:集群完整确认,Leader会等待所有in-sync的follower节点都确认收到消息后,再返回确认信息;
我们可以根据消息的重要程度,设置不同的确认模式。默认为1。
* retries:发送失败时Producer端的重试次数,默认为0
* batch.size:当同时有大量消息要向同一个分区发送时,Producer端会将消息打包后进行批量发送。如果设置为0,则每条消息都独立发送。默认为16384字节
* linger.ms:发送消息前等待的毫秒数,与batch.size配合使用。在消息负载不高的情况下,配置linger.ms能够让Producer在发送消息前等待一定时间,以积累更多的消息打包发送,达到节省网络资源的目的。默认为0
* key.serializer/value.serializer:消息key/value的序列器Class,根据key和value的类型决定
* buffer.memory:消息缓冲池大小。尚未被发送的消息会保存在Producer的内存中,如果消息产生的速度大于消息发送的速度,那么缓冲池满后发送消息的请求会被阻塞。默认33554432字节(32MB)

消费者常用配置:
* bootstrap.servers/key.deserializer/value.deserializer:和Producer端的含义一样,不再赘述
* fetch.min.bytes:每次最小拉取的消息大小(byte)。Consumer会等待消息积累到一定尺寸后进行批量拉取。默认为1,代表有一条就拉一条
* max.partition.fetch.bytes:每次从单个分区中拉取的消息最大尺寸(byte),默认为1M
* group.id:Consumer的group id,同一个group下的多个Consumer不会拉取到重复的消息,不同group下的Consumer则会保证拉取到每一条消息。注意,同一个group下的consumer数量不能超过分区数。
* enable.auto.commit:是否自动提交已拉取消息的offset。提交offset即视为该消息已经成功被消费,该组下的Consumer无法再拉取到该消息(除非手动修改offset)。默认为true
* auto.commit.interval.ms:自动提交offset的间隔毫秒数,默认5000。offset就是向系统提交的确认信息。

说明:
本 例中采用的是自动提交offset,Kafka client会启动一个线程定期将offset提交至broker。假设在自动提交的间隔内发生故障(比如整个JVM进程死掉),那么有一部分消息是会被 重复消费的。要避免这一问题,可使用手动提交offset的方式。构造consumer时将enable.auto.commit设为false,并在代 码中用consumer.commitSync()来手动提交。

更多的Producer配置见官网
http://kafka.apache.org/documentation.html#producerconfigs

猜你喜欢

转载自blog.csdn.net/huxiny/article/details/80195268