Kafka-4、运维

一、集群环境规划
1、操作系统
Kafka为JVM的框架,Java为跨平台语言,理论上Kafka可以部署到任意支持Java的操作系统上。但是部署到不同系统还是有区别的。Linux比Windows等其他操作系统更适合部署Kafka。主要原因有I/O模型的使用和网络传输的效率。
Kafka新版本clients的设计底层使用了Java的Selector机制,而后者在Linux上的实现机制就是epoll模型。但在Windows上Selector实现的机制为select模型而非IOCP模型,只有在Java NIO2才是使用IOCP模型实现的。因此部署在Linux上比Windows上能得到更高效的I/O处理性能。
Kafka需要大量的通过网络与磁盘进行数据交互,这些操作都是通过Java的FileChannel.transferTo方法实现的,在Linux底层使用sendfile系统调用,即零拷贝Zero Copy技术。
综上,推荐生产环境使用Linux操作系统

2、磁盘
Kafka大量使用磁盘。每条消息都必须被持久化存储在磁盘中,只有一定数据的broker成功接收后才统计clients消息发送成功,因此消息越快被保存到磁盘上clients的请求延时越低。
1)、机械硬盘HDD还是固态硬盘SSD
机械硬盘成本低容量大,固态硬盘性能好成本大。需要根据公司自身需求选择对应类型的硬盘。但是Kafka使用磁盘的方式,一定程度上缩小了两种硬盘的差距,Kafka是顺序写磁盘的,磁盘顺序I/O的性能,差距不大。追求性价比的公司可以使用机械硬盘,当然使用SSD性能更好。

2)、普通磁盘JBOD还是磁盘整列RAID
RAID作为Kafka底层存储有两个优势:提供冗余的数据存储空间和自带的负载均衡。不过Kafka自身已经提供这两种特性,我们可以通过副本机制提供冗余和高可靠性,通过分散到各个节点的领导选举机制实现负载均衡。建议选择JBOD。另外尽量不要使用网络存储NAS。

3)、磁盘容量规划
Kafka需要多大磁盘容量,需要根据自身业务场景和存储需要来计算。磁盘容量与新增消息数、消息存留时间、平均消息大小、副本数、是否启用压缩有关。
假如每天会产生1亿条数据,每条消息保存两份并保留1周的时间,平均一条消息的大小是1KB。那么1亿21KB/1000/1000=200GB 磁盘空间,还需预留10%磁盘空间存储其他文件,则为210GB,还要保存一周210GB*7=1.5TB。这是在五压缩的情况下,如果clients启用了消息压缩,可以预估一个压缩比,相乘即得到磁盘容量。

3、内存
Kafka虽然打了依靠文件系统和磁盘来保存消息,但还是会对消息进行缓存,缓存在操作系统的页缓存page cache。
Kafka持久化消息的时候,仅将消息写入page cache中,之后写到磁盘的操作是由系统完成的。consumer读取消息时也会先从page cache中读取,如果命中了则不需要物理I/O操作,提高consumer的整体性能。所以我们尽量分配给多的内存给操作系统的page cache。
Kafka对Java堆内存使用不是很多,Kafka中的消息会很快的进行垃圾回收GC,不要为broker设置过大的堆内存,最好不超过6GB。
另外需要把page cache的大小与实际环境的日志段大小做比较。page cache大小至少要大于一个日志段的大小。

4、cpu
Kafka不属于计算密集型系统,Kafka的CPU追求多核而非搞时钟频率。
使用多核系统,CPU核数最好大于8。

5、带宽
Kafka在网络间传输大量数据的分布式数据管道,带宽资源很容易造成瓶颈。快速且稳定的网络环境是搭建Kafka集群的前提。当前主流的网络环境千兆位网络和万兆位网络都满足Kafka集群的使用。
根据带宽和磁盘空间,可以计算出整个集群需要的broker数。
如在1GB/s的带宽中,业务目标是在1小时内处理1TB数据,这时需要多少个broker呢?1GB/s的带宽中,假如分配到Kafka的为70%带宽,则为710M/s,还需要预留2/3缓冲,即240M/s,如果要1小时内处理1TB数据,即每秒处理2336M数据,那么需要2336/240约10个broker。
尽量使用高速网络;根据自身带宽评估broker的数量;避免使用跨机房网络。

6、建议配置
操作系统:Linux
CPU:24核
内存:32GB
磁盘:1TB 7200转SAS盘两块
带宽:1GB/s

二、参数设置
1、系统参数
部署在Linux下,需要调整以下参数:
1)、文件描述符限制

ulimit -n 100000

2)、设置系统socket缓冲区大小,最好设置为128KB
3)、最好使用Ext4或者XFS文件系统,推荐XFS类型文件系统
查看文件系统类型

df -T 

4)、关闭swap,将vm.swappiness设置为个较小的值。
查看swap值

cat /proc/sys/vm/swappiness

临时设置,重启后失效

sysctl vm.swappiness=10

永久设置

echo "vm.swappiness=9" >> /etc/sysctl.conf
/sbin/sysctl -p

5)、设置更长的flush时间。
这里初始值为3000,设置为原来的5倍。

echo "vm.dirty_expire_centisecs=15000" >> /etc/sysctl.conf
/sbin/sysctl -p

2、JVM参数
通常broker的内存设置不大于6G,Java8推荐使用G1垃圾收集器。
-Xmx6g -Xms6g -XX:MetaspaceSize=96m -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:G1HeapRegionSize=16M -XX:MinMetaspanceFreeRatio=50 -XX:MaxMetaspanceFeeRatio=80

3、Broker参数
详细参数参考官网:http://kafka.apache.org/documentation/#brokerconfigs
broker.id:Kafka服务broker的ID,全局唯一整数,使用该参数表示broker。默认值为-1。如果不指定会自动生成一个唯一值。

log.dirs:Kafka持久化消息的目录。最好设置在磁盘空间足够的位置。如果使用多块磁盘,建议设置多个目录(用逗号分隔),这样可以把负载均匀的分布到各个目录,N个磁头可以同时工作,提高吞吐量。如果不设置默认保存到/tep/kafka-logs目录下。

zookeeper.connect:Kafka使用的Zookeeper集群地址,可以使用多个值(用逗号分隔)。如果一个Zookeeper管理多个Kafka,需要在后面添加目录,比如zk1:2181,zk2:2181,zk3:2181/kafka_cluster1 中/kafka_cluster1为添加的路径,如果不设置kafka的元数据信息默认保存在Zookeeper的根目录。

listeners:broker监听器位置,格式为[协议]😕/[主机名]:[端口]。可以配置多个值(用逗号分隔)。Kafka支持的协议类型包括PLAINTEXT、SSL、SASL_SSL等,使用PLAINTEXT就足够了,如果启用了安全协议使用SSL、SASL_SSL。

advertised.listeners:注册到Zookeeper中的主机名和端口,格式为[协议]😕/[主机名]:[端口],外网访问时需要注释掉listeners参数,启用该参数。

4、Topic参数
详细参数参考官网:http://kafka.apache.org/documentation/#topicconfigs

二、集群管理
2.1、broker管理
2.1.1、启动broker
默认启动,默认使用config/server.properties配置文件。

bin/kafka-server-start.sh

使用上面启动方式当会话关闭时会停止kafka服务,我们可以使用daemon参数或nohup方式后台启动。
-deamon参数启动:

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

nohup启动

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

启动后最好看一下日志是否报错,日志在logs目录下,文件名为server.log。如果发现started输出,则broker启动成功。

2.1.2、停止broker
如果为前台启动,即没加-daemon参数和nohup启动,在终端Ctrl+C,可以发出终止信号,关闭broker。
如果为后台启动,推荐使用kafka停止脚本停止broker。

bin/kafka-server-stop.sh

上面的停止脚本会停止该服务器上所有kafka进程。
如果使用kafka-server-stop.sh不能关闭broker。建议获取到kafka的pid后使用以下命令停止,不建议使用kill -9命令停止broker。

kill -s term PID

2.1.3、添加broker
只需要为新增的broker的配置文件中broker.id设置一个唯一值,然后启动即可。Kafka集群能自动发现启动的broker并同步元数据信息。
新添加的broker不会自动分配已有的topic分区,需要用户手动重新分配分区。后面新建的topic会使用新建的broker。

2.1.4、设置JMX端口
Kafka提供了JMX指标用户集群的监控,如果要使用这些指标需要指定JMX端口。

export JMX_PORT=9995 bin/kafka-server-start.sh -daemon config/server.properties

2.1.5、升级broker
以下示例将Kafka从0.10.0.0版本升级到0.10.2.0版本。
1、更新broker的通信版本和消息版本,需要更新所有broker的配置文件,版本为当前Kafka的版本。

inter.broker.protocol.version=0.10.0
log.message.format.version=0.10.0

2、更新代码,依次重启broker,将0.10.2.0版本的Kafka二进制文件覆盖原目录,依次重启broker。
3、再次更新broker的通信版本和消息版本,此次版本为升级后的Kafka版本。

inter.broker.protocol.version=0.10.2
log.message.format.version=0.10.2

4、依次重启broker。

2.2、topic管理
2.2.1、创建topic
1、kafka-topic.sh创建
创建3个分区两个副本的topic。

bin/kafka-topics.sh --zookeeper zk1:2181,zk2:2182,zk3:2183 --create --partitions 3 --replication-factor 2 --topic test-topic

相关参数:
–partitions:分区数
–replication-factor:副本数
–if-not-exists:是否存在topic,如果存在同名不会报错
–replica-assigment:手动指定分区分配,例如创建分区数为4,副本数为2的topic。0:1,1:2,0:2,1:2。

2、java代码创建
topic Bean类

package org.example.kafka.topic;

public class KafkaTopic {
    private String topicName;       // topic 名称
    private Integer partition;      // partition 分区数量
    private Integer replication;    // replication 副本数量
    private String descrbe;

    public String getTopicName() {
        return topicName;
    }

    public void setTopicName(String topicName) {
        this.topicName = topicName;
    }

    public Integer getPartition() {
        return partition;
    }

    public void setPartition(Integer partition) {
        this.partition = partition;
    }

    public Integer getReplication() {
        return replication;
    }

    public void setReplication(Integer replication) {
        this.replication = replication;
    }

    public String getDescrbe() {
        return descrbe;
    }

    public void setDescrbe(String descrbe) {
        this.descrbe = descrbe;
    }

    @Override
    public String toString() {
        return "KafkaTopic [topicName=" + topicName + ", partition=" + partition
                + ", replication=" + replication + ", descrbe=" + descrbe +"]";
    }

}

创建topic工具类

package org.example.kafka.topic;

import kafka.admin.AdminUtils;
import kafka.admin.RackAwareMode;
import kafka.utils.ZkUtils;
import org.apache.kafka.common.security.JaasUtils;

import java.util.Properties;

public class KafkaTopicUtils {
    public static void createKafaTopic(String ZkStr,KafkaTopic topic) {
        ZkUtils zkUtils = null;
        try {
            zkUtils = ZkUtils.
                    apply(ZkStr, 30000, 30000, JaasUtils.isZkSecurityEnabled());
            // 查看是否存在该Topic
            if (!AdminUtils.topicExists(zkUtils, topic.getTopicName())) {
                AdminUtils.createTopic(zkUtils, topic.getTopicName(), topic.getPartition(),
                        topic.getReplication(), new Properties(), new RackAwareMode.Enforced$());
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            if(zkUtils!=null)
                zkUtils.close();
        }
    }

    public static void deleteKafaTopic(String ZkStr,KafkaTopic topic) {
        ZkUtils zkUtils = null;
        try {
            zkUtils = ZkUtils.
                apply(ZkStr, 30000, 30000, JaasUtils.isZkSecurityEnabled());
            // 查看是否存在该Topic
            if (!AdminUtils.topicExists(zkUtils, topic.getTopicName())){
                AdminUtils.deleteTopic(zkUtils, topic.getTopicName());
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            if(zkUtils!=null)
                zkUtils.close();
        }
    }

}

启动类

package org.example.kafka.topic;

public class KafkaTopicTest {
    public static void main(String[] args) throws Exception{
        //zookeeper地址:端口号
        String ZkStr = "zk1:2181,zk2:2182,zk3:2183";

        //topic对象
        KafkaTopic topic = new KafkaTopic();
        topic.setTopicName("testTopic");  //topic名称
        topic.setPartition(3);            //分区数量设置为3
        topic.setReplication(2);          //副本数量设置为2

        //创建topic
        KafkaTopicUtils.createKafaTopic(ZkStr,topic);
        System.out.println("create kafka topic success");
        //暂停5分钟后删除,查看topic是否创建成功
        Thread.sleep(1000*60*5);
        //删除topic
        KafkaTopicUtils.deleteKafaTopic(ZkStr,topic);
        System.out.println("delete kafka topic success");
    }
}

启动后,查看topic list

bin/kafka-topics.sh --zookeeper zk1:2181,zk2:2182,zk3:2183 --list

3、修改Zookeeper节点创建(不推荐使用)
在Zookeeper的/brokers/topics下写入topic名称命名的子节点。

2.2.2、删除topic
1、kafka-topic.sh删除

bin/kafka-topics.sh --zookeeper zk1:2181,zk2:2182,zk3:2183 --delete --topic test-topic

2、java代码删除
参见2.2.1

3、修改Zookeeper节点删除(不推荐使用)
在Zookeeper的/admin/delete_topics下写入子节点。

2.2.3、查看topic
1、查看topic列表

 bin/kafka-topics.sh --zookeeper zk1:2181,zk2:2182,zk3:2183 --list

2、查看topic详情

bin/kafka-topics.sh --zookeeper zk1:2181,zk2:2182,zk3:2183 --describe --topic test

2.2.4、修改topic
1、修改topic
修改topic的分区数为4,topic新增分区当topic消息有key时,会重新计算分区,分区修改只能增加不能减少。

bin/kafka-topics.sh --zookeeper zk1:2181,zk2:2182,zk3:2183 --alter --partitions 4 --topic test

2、topic动态配置
使用kafka-configs.sh可以动态配置参数。
1)、添加topic配置

bin/kafka-configs.sh --zookeeper zk1:2181,zk2:2182,zk3:2183 --alter --entity-type topics --entity-name test --add-config preallocate = true,segment.bytes

2)、查看topic配置

bin/kafka-configs.sh --zookeeper zk1:2181,zk2:2182,zk3:2183 --describe --topic test

3)、删除topic配置

bin/kafka-configs.sh --zookeeper zk1:2181,zk2:2182,zk3:2183 --alter --entity-type topics --entity-name test --delete-config preallocate

2.3、consumer管理
2.3.1、创建消费者组

bin/kafka-console-consumer.sh --bootstrap-server=kafka1:9092 --topic test --from-beginning --consumer-property group.id=test-group1

2.3.2、查看消费者组
1、查看列表

bin/kafka-consumer-groups.sh --bootstrap-server kafka1:9092 --list

2、查看详情

bin/kafka-consumer-groups.sh --bootstrap-server kafka1:9092 --describe --group test-group1

2.3.3、重新设置消费者组位移

bin/kafka-consumer-groups.sh --bootstrap-server kafka1:9092 --group test-group1 --reset-offsets --all-topics --to-earliest --execute

设置消费组
–group test-group1:设置消费组名称

设置topic
–all-topics:消费组下所有topic设置
–topic test1,–topic test2:消费组下test1和test2 topic设置
–topic test1:0,1,2:指定topic名称下的分区设置

设置位移策略
–to-earliest:调整到分区当前最早位移处
–to-latest:调整到分区当前最新位移处
–to-current:调整到分区当前位移处
–to-offset 5000:调整到分区指定位移处
–shit-by N:调整到分区当前位移+N位移处
–to-datetime:调整到大于指定时间的最早位移处
–by-duration:调整到距离当前时间指定间隔的位移处

2.3.3、删除消费者组

bin/kafka-consumer-groups.sh --zookeeper zk1:2181 --delete--group test-group1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值