kafka单点搭建与java api使用

  1. 解压缩

kafka_2.11-2.0.0.tgz

  1. 配置jdk
  2. Zookeeper

本例使用kafka自带zookeeper

可使用自定义的zookeeper,需要修改kafka:server.properties

  1. 配置

server.properties

broker.id=0

advertised.listeners=PLAINTEXT://192.168.166.2:9092

log.dirs=/opt/kafka/log

zookeeper.connect=localhost:2181

consumer.properties:

group.id的值

  1. 以次启动测试:

Zookeeper启动:

[root@node122 bin]# nohup ./zookeeper-server-start.sh  /opt/kafka/config/zookeeper.properties &

Kafka启动:

[root@node122 bin]#nohup  ./kafka-server-start.sh  /opt/kafka/config/server.properties &

5、测试:

[root@node122 bin]# ./kafka-topics.sh --create --zookeeper localhost:2181  --replication-factor 1 --partitions 1 --topic test

Created topic "test".

[root@node122 bin]# ./kafka-topics.sh --list --zookeeper localhost:2181

 

生产者和消费者测试:

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

 

./kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic mytopic

6、创建启动和停止脚本

启动脚本:

#!/bin/sh

# start zookeeper

nohup sh /opt/kafka/bin/zookeeper-server-start.sh  /opt/kafka/config/zookeeper.properties &

 

#wait 4s

sleep 4

 

#start kafka

nohup sh /opt/kafka/bin/kafka-server-start.sh  /opt/kafka/config/server.properties &

 

停止脚本:

#!/bin/sh

#stop zookeeper

sh  /opt/kafka/bin/zookeeper-server-stop.sh  /opt/kafka/config/zookeeper.properties

 

#wait 4s

sleep 4

 

#stop kafka

sh /opt/kafka/bin/kafka-server-stop.sh /opt/kafka/config/server.properties

 

添加执行权限

chmod +x kafkastart.sh

chmod +x kafkastop.sh

 

7、随开机启动配置

vi /etc/rc.d/rc.local #编辑,在最后添加一行

nohup sh /opt/kafka/kafkastart.sh & #设置开机自动在后台运行脚本

:wq! #保存退出

8、java api使用 (创建maven项目)

  1. Pom.xml:
<dependency>
  <groupId>org.apache.kafka</groupId>
  <artifactId>kafka-clients</artifactId>
  <version>2.0.0</version>
</dependency>

<dependency>
  <groupId>org.apache.kafka</groupId>
  <artifactId>kafka_2.11</artifactId>
  <version>2.0.0</version>
</dependency>

 2)生产者工具类

public class KafkaProduceUtil {
    private static KafkaProduceUtil kafkaProduceUtil = null;
    public  Producer<String, String> producer = null;

    private KafkaProduceUtil(){
        if(producer == null) {
            Properties props = new Properties();
            // 配置
            props.put("bootstrap.servers","192.168.166.2:9092");
            // 配置value的序列化类
            props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
            // 配置key的序列化类
            props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");

            /**
             * 判别请求是否为完整的条件(就是是判断是不是成功发送了)。
             * 我们指定了“all”将会阻塞消息,这种设置性能最低,但是是最可靠的
             */
            props.put("acks", "-1");
            /**
             * 如果请求失败,生产者会自动重试,我们指定是0次,
             * 如果启用重试,则会有重复消息的可能性
             */
            props.put("retries", 0);
            props.put("batch.size", 16384);
            /**
             * 减少请求的数量,可以设置linger.ms大于0。
             * 这将指示生产者发送请求之前等待一段时间,希望更多的消息填补到未满的批中
             */
            props.put("linger.ms", 1);
            /**
             * 控制生产者可用的缓存总量,如果消息发送速度比其传输到服务器的快,将会耗尽这个缓存空间。
             * 当缓存空间耗尽,其他发送调用将被阻塞,阻塞时间的阈值通过max.block.ms设定,之后它将抛出一个TimeoutException
             */
            props.put("buffer.memory", 33554432);
            producer = new KafkaProducer<String, String>(props);
        }
    }

    /**
     *  并发单例模式
     * @return
     */
    public static synchronized KafkaProduceUtil getInstance(){
        if(kafkaProduceUtil == null) {
            kafkaProduceUtil = new KafkaProduceUtil();
        }
        return kafkaProduceUtil;
    }

    public void closeConnect() {
        if(producer != null){
            producer.close();
        }
    }

3)消费者工具类

public class KafkaConsumeUtile {
    private static KafkaConsumeUtile kafkaConsumeUtile = null;
    public KafkaConsumer<String, String> consumer = null;

    private KafkaConsumeUtile(){
        if(consumer == null) {
            Properties props = new Properties();
            /**
             * 进程池瓜分消费和处理消息的工作。这些进程可以在同一台机器运行,
             * 也可分布到多台机器上,增加可扩展性和容错性,相同group.id的消费者将视为同一个消费者组,
             * group.id的值 与config中consumer.properties的值一致
             */
            props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.166.2:9092");
            props.put(ConsumerConfig.GROUP_ID_CONFIG ,"test-consumer-group") ;
            props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true");
            props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000");
            props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
            props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
            consumer = new KafkaConsumer<>(props);
        }
    }

    public static synchronized KafkaConsumeUtile getInstance() {
        if(kafkaConsumeUtile == null) {
            kafkaConsumeUtile = new KafkaConsumeUtile();
        }
        return kafkaConsumeUtile;
    }

}

4)生产者测试类

public class KafkaProduce {

    public static void testProduce() {
        KafkaProduceUtil kafkaProduceUtil = KafkaProduceUtil.getInstance();
        /**
         * send是异步的,并且一旦消息被保存在等待发送的消息缓存中,此方法就立即返回。
         * 这样并行发送多条消息而不阻塞去等待每一条消息的响应。
         * 发送的结果是一个RecordMetadata,它指定了消息发送的分区,分配的offset和消息的时间戳。
         */
        for(int i = 0; i < 100; i++){
            kafkaProduceUtil.producer.send(new ProducerRecord<String, String>("pp","pp:"+i,"pp:"+i),
                    new Callback() {
                        @Override
                        public void onCompletion(RecordMetadata metadata, Exception e) {
                            if (e != null) {
                                // 如果在centos上测试没问题;这里发送超时时,一般时因为server.properties中;
                                //
                                e.printStackTrace();
                            } else {
                                System.out.println("The offset of the record we just sent is: " + metadata.offset());
                            }
                        }
                    });
        }
        kafkaProduceUtil.closeConnect();
    }

    public static void main(String[] args) {
        testProduce();
    }
}

5)消费者测试类

public class KafkaConsume {

    public static void testConsume() {
        KafkaConsumeUtile kafkaConsumeUtile = KafkaConsumeUtile.getInstance();
        kafkaConsumeUtile.consumer.subscribe(Arrays.asList("pp"));

        while (true) {
            /**
             * 调用poll(long)时,消费者将自动加入到组中。
             * 只要持续的调用poll,消费者将一直保持可用,并继续从分配的分区中接收消息。
             * 此外,消费者向服务器定时发送心跳。 如果消费者崩溃或无法在session.timeout.ms配置的时间内发送心跳,
             * 则消费者将被视为死亡,并且其分区将被重新分配
             */
            ConsumerRecords<String, String> records = kafkaConsumeUtile.consumer.poll(100);
            for(ConsumerRecord<String, String> record : records) {
                System.out.println("收到消息:" + record.key() + ":" +record.value());
            }
        }
    }

    public static void main(String[] args) {
        testConsume();
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值