• Kafka集群搭建


    一、Kafka集群搭建

    1、环境构建

     安装kafka集群之前,确保zookeeper服务已经正常运行,这里3台zookeeper准备工作都已完成,三台主机分别为:192.168.3.220,192.168.3.221,192.168.3.222

    wget http://mirror.bit.edu.cn/apache/kafka/2.1.1/kafka_2.11-2.1.1.tgz ##拉取压缩包到本地进行解压安装

    tar -xf kafka_2.11-2.1.1.tgz ##解压文件

    mv kafka-2.1.1-src /usr/local/kafka ##移动到/usr/local/kafka目录下面

    2、编辑配置

    cd /usr/local/kafka/config

    vim server.properties

    修改配置文件的以下属性

    ## 强调这个ID在集群中必须是唯一否则会出现ID冲突问题
    broker.id=0 
    ## 配置kafka的服务监听端口
    ## 如果配置0.0.0.0则绑定全部网卡,如果默认像下面这样,kafka会绑定默认的所有网卡ip,一般在机器中hosts,hostname都要正确配置,这里默认即可;然后下面的port默认9092不用配置,如果自定义端口号需要设置和listeners的一致,这个是kafka服务监听的端口号. 
    listeners=PLAINTEXT://192.168.3.220:9092
    ## 配置日志目录,建议在kafka的根目录创建一个日志目录
    log.dirs=/usr/local/kafka/logs
    ## 配置分区个数
    num.partitions=1
    ## 配置Zookeeper集群字符串
    zookeeper.connect=192.168.3.220:2181,192.168.3.221:2181,192.168.3.222:2181

    把刚的配置远程拷贝到其他的2台机器上面

    scp -r /usr/local/kafka 192.168.3.221:/usr/local/

    scp -r /usr/local/kafka 192.168.3.222:/usr/local/

    并修改上面配置文件的属性

    broker.id和listeners就OK

    3、启动kafka集群

    /usr/local/kafka/bin/kafka-server-start.sh -daemon /usr/local/kafka/config/server.properties

    /usr/local/kafka/bin/kafka-server-start.sh -daemon /usr/local/kafka/config/server.properties

    /usr/local/kafka/bin/kafka-server-start.sh -daemon /usr/local/kafka/config/server.properties

    4、测试kafka集群

    4.1、创建和查看消息主题

    连接zookeeper,创建一个名为test-topic的topic

    sh kafka-topics.sh --create --zookeeper 192.168.3.220:2181,192.168.3.221:2181,192.168.3.222:2181 --replication-factor 3 --partitions 3 --topic test-topic 
    Created topic "test-topic".

    查看此topic属性

    sh kafka-topics.sh --describe --zookeeper 192.168.3.220:2181,192.168.3.221:2181,192.168.3.222:2181 --topic test-topic
    Topic:test-topic    PartitionCount:3    ReplicationFactor:3 Configs:
        Topic: test-topic       Partition: 0    Leader: 2       Replicas: 2,1,3 Isr: 2,1
        Topic: test-topic       Partition: 1    Leader: 3       Replicas: 3,2,1 Isr: 3,2,1
        Topic: test-topic       Partition: 2    Leader: 1       Replicas: 1,3,2 Isr: 1
     

    查看已经创建的topic列表

    sh kafka-topics.sh --list --zookeeper 192.168.3.220:2181,192.168.3.221:2181,192.168.3.222:2181
    test-topic

    4.2、创建消息生产者发送消息

    sh kafka-console-producer.sh --broker-list 192.168.3.220:9092,192.168.3.221:9092,192.168.3.222:9092 --topic test-topic

    4.3、创建消息消费者接收消息

    sh kafka-console-consumer.sh --bootstrap-server 192.168.3.220:9092,192.168.3.221:9092,192.168.3.222:9092 --topic test-topic --from-beginning

     

    ★错误记录:-bash: ./kafka-server-start.sh: Permission denied

    在执行启动启动kafka集群的时候,报错没有权限操作该文件,直接通过 chmod 777 zookeeper-server-start.sh命令给无权限的文件更改权限。

    [2019-02-28 22:00:23,657] WARN [Producer clientId=console-producer] Connection to node 1 (/192.168.3.220:9092) could not be established. Broker may not be available. (org.apache.kafka.clients.NetworkClient)

    这个是因为防火墙没有放行端口

    firewall-cmd --add-port=9092/tcp --permanent

    5、Java连接生成消息和发送消息

    引入依赖

    <dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka_2.12</artifactId>
        <version>2.1.1</version>
    </dependency>

     

    编写生产者代码

    import org.apache.kafka.clients.producer.KafkaProducer;
    import org.apache.kafka.clients.producer.Producer;
    import org.apache.kafka.clients.producer.ProducerRecord;
     
    import java.util.Properties;
    ​
    ​
    public class KafkaProducer {
     
        public static void main(String[] args) throws InterruptedException {
            Properties props = new Properties();
            //kafka服务器地址
            props.put("bootstrap.servers", "192.168.3.220:9092,192.168.3.221:9092,192.168.3.222:9092");
            //ack是判断请求是否为完整的条件(即判断是否成功发送)。all将会阻塞消息,这种设置性能最低,但是最可靠。
            props.put("acks", "1");
            //retries,如果请求失败,生产者会自动重试,我们指定是0次,如果启用重试,则会有重复消息的可能性。
            props.put("retries", 0);
            //producer缓存每个分区未发送消息,缓存的大小是通过batch.size()配置设定的。值较大的话将会产生更大的批。并需要更多的内存(因为每个“活跃”的分区都有一个缓冲区)
            props.put("batch.size", 16384);
            //默认缓冲区可立即发送,即便缓冲区空间没有满;但是,如果你想减少请求的数量,可以设置linger.ms大于0.这将指示生产者发送请求之前等待一段时间
            //希望更多的消息补填到未满的批中。这类似于tcp的算法,例如上面的代码段,可能100条消息在一个请求发送,因为我们设置了linger时间为1ms,然后,如果我们
            //没有填满缓冲区,这个设置将增加1ms的延迟请求以等待更多的消息。需要注意的是,在高负载下,相近的时间一般也会组成批,即使是linger.ms=0。
            //不处于高负载的情况下,如果设置比0大,以少量的延迟代价换取更少的,更有效的请求。
            props.put("linger.ms", 1);
            //buffer.memory控制生产者可用的缓存总量,如果消息发送速度比其传输到服务器的快,将会耗尽这个缓存空间。当缓存空间耗尽,其他发送调用将被阻塞,阻塞时间的阈值
            //通过max.block.ms设定,之后他将抛出一个TimeoutExecption。
            props.put("buffer.memory", 33554432);
            //key.serializer和value.serializer示例:将用户提供的key和value对象ProducerRecord转换成字节,你可以使用附带的ByteArraySerizlizaer或StringSerializer处理简单的byte和String类型.
            props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
            props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
            //设置kafka的分区数量
            props.put("kafka.partitions", 12);
            
            Producer<String, String> producer = new KafkaProducer<>(props);
            for (int i = 0; i < 50; i++){
                System.out.println("key-->key"+i+"  value-->vvv"+i);
                producer.send(new ProducerRecord<String, String>("aaa", "key"+i, "vvv"+i));
                Thread.sleep(1000);
            }
            producer.close();
        }
    }

    用于建立消费者的相关参数说明及其默认值参见producerconfigs,此处对代码中用到的几个参数进行解释:

    bootstrap.servers:用于初始化时建立链接到kafka集群,以host:port形式,多个以逗号分隔host1:port1,host2:port2;

    acks:生产者需要server端在接收到消息后,进行反馈确认的尺度,主要用于消息的可靠性传输;acks=0表示生产者不需要来自server的确认;acks=1表示server端将消息保存后即可发送ack,而不必等到其他follower角色的都收到了该消息;acks=all(or acks=-1)意味着server端将等待所有的副本都被接收后才发送确认。

    retries:生产者发送失败后,重试的次数

    batch.size:当多条消息发送到同一个partition时,该值控制生产者批量发送消息的大小,批量发送可以减少生产者到服务端的请求数,有助于提高客户端和服务端的性能。

    linger.ms:默认情况下缓冲区的消息会被立即发送到服务端,即使缓冲区的空间并没有被用完。可以将该值设置为大于0的值,这样发送者将等待一段时间后,再向服务端发送请求,以实现每次请求可以尽可能多的发送批量消息。

    batch.size和linger.ms是两种实现让客户端每次请求尽可能多的发送消息的机制,它们可以并存使用,并不冲突。

    buffer.memory:生产者缓冲区的大小,保存的是还未来得及发送到server端的消息,如果生产者的发送速度大于消息被提交到server端的速度,该缓冲区将被耗尽。

    key.serializer,value.serializer说明了使用何种序列化方式将用户提供的key和vaule值序列化成字节。

    编写消费端代码

    import org.apache.kafka.clients.consumer.ConsumerRecord;
    import org.apache.kafka.clients.consumer.ConsumerRecords;
    import org.apache.kafka.clients.consumer.KafkaConsumer;
     
    import java.util.Arrays;
    import java.util.Properties;
    s
    public class KafkaConsumer {
     
        public KafkaConsumer<String, String>  getConsmer() {
            Properties props = new Properties();
            //设置kafka服务器
            props.put("bootstrap.servers", "192.168.3.220:9092,192.168.3.221:9092,192.168.3.222:9092");
            //消费者群组ID,发布-订阅模式,即如果一个生产者,多个消费者都要消费,那么需要定义自己的群组,同一个群组内的消费者只有一个能消费到消息
            props.put("group.id", "test");
            //true,消费者的偏移量将在后台定期提交;false关闭自动提交位移,在消息被完整处理之后再手动提交位移
            props.put("enable.auto.commit", "true");
            //如何设置为自动提交(enable.auto.commit=true),这里设置自动提交周期
            props.put("auto.commit.interval.ms", "1000");
            //session.timeout.ms:在使用kafka的组管理时,用于检测消费者故障的超时
            props.put("session.timeout.ms", "30000");
            //key.serializer和value.serializer示例:将用户提供的key和value对象ProducerRecord转换成字节,你可以使用附带的ByteArraySerizlizaer或StringSerializer处理简单的byte和String类型.
            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);
            return consumer;
        }
     
        
        
        public static void main(String[] args) {
            KConsumer kconsumer =  new KConsumer();
            KafkaConsumer<String, String> consumer = kconsumer.getConsmer();
            
            consumer.subscribe(Arrays.asList("aaa"));
            while (true) {
                ConsumerRecords<String, String> records = consumer.poll(100);
                for (ConsumerRecord<String, String> record : records)
                    System.out.println("offset =  "+record.offset()+", key = "+record.key()+", value = "+ record.value());
            }
        }
    }

     

     

     

  • 相关阅读:
    How to use my view helpers in my ActionMailer views?
    大败笔,状态机
    把程序进行上线部署调试了,
    支付接口心得
    rails3 正则路由
    linux下配置Mysql远程访问,不受ip限制
    ActionController::InvalidAuthenticityToken解决办法
    支付宝接口错误
    DHTML 中的绝对定位
    部署备份
  • 原文地址:https://www.cnblogs.com/lm970585581/p/13398341.html
Copyright © 2020-2023  润新知