Kafka java api-生产者代码、高性能吞吐

来源:互联网 发布:tcp网络调试助手 编辑:程序博客网 时间:2024/05/18 03:47

前面做过命令行让生产者发送消息,现在使用java api来进行消息的生产,以及解释kafka高性能是如何实现(来源于学习资料)。
使用shell创建topic和发送消息如下:

#参数:zookeeper连接地址和端口号,副本数(包括自身),使用几个partition,topic的名称[root@mini1 bin]# ./kafka-topics.sh --create --zookeeper mini1:2181 --replication-factor 2 --partitions 3 --topic orderMqCreated topic "orderMq".[root@mini1 bin]# kafka-console-producer.sh --broker-list mini1:9092 --topic orderMqhello tomhi jerryspring hhaahxixinini

下面使用java api来发送消息
注:如果topic已经存在那么肯定就不创建了,但是不存在则会创建。

public class KafkaProducerSimple {    public static void main(String[] args) {        /**         * 1、指定当前kafka producer生产的数据的目的地         *  创建topic可以输入以下命令,在kafka集群的任一节点进行创建。         *  bin/kafka-topics.sh --create --zookeeper mini1:2181 --replication-factor 2 --partitions 3 --topic test         */        String TOPIC = "orderMQ";        /**         * 2、读取配置文件         */        Properties props = new Properties();        /*         * key.serializer.class默认为serializer.class  key的序列化使用哪个类         */        props.put("serializer.class", "kafka.serializer.StringEncoder");        /*         * kafka broker对应的主机,格式为host1:port1,host2:port2         */        props.put("metadata.broker.list", "mini1:9092,mini2:9092,mini3:9092");        /*         * request.required.acks,设置发送数据是否需要服务端的反馈,有三个值0,1,-1         * 0,意味着producer永远不会等待一个来自broker的ack,这就是0.7版本的行为。         * 这个选项提供了最低的延迟,但是持久化的保证是最弱的,当server挂掉的时候会丢失一些数据。         * 1,意味着在leader replica已经接收到数据后,producer会得到一个ack。         * 这个选项提供了更好的持久性,因为在server确认请求成功处理后,client才会返回。         * 如果刚写到leader上,还没来得及复制leader就挂了,那么消息才可能会丢失。         * -1,意味着在所有的ISR都接收到数据后,producer才得到一个ack。         * 这个选项提供了最好的持久性,只要还有一个replica存活,那么数据就不会丢失         */        props.put("request.required.acks", "1");        /*         * 可选配置,如果不配置,则使用默认的partitioner partitioner.class         * 默认值:kafka.producer.DefaultPartitioner         * 用来把消息分到各个partition中,默认行为是对key进行hash。         */        props.put("partitioner.class", "com.scu.kafka.MyLogPartitioner");//        props.put("partitioner.class", "kafka.producer.DefaultPartitioner");        /**         * 3、通过配置文件,创建生产者         */        Producer<String, String> producer = new Producer<String, String>(new ProducerConfig(props));        /**         * 4、通过for循环生产数据         */        for (int messageNo = 1; messageNo < 100000; messageNo++) {            /**             * 5、调用producer的send方法发送数据             * 注意:这里需要指定 partitionKey,用来配合自定义的MyLogPartitioner进行数据分发             */            producer.send(new KeyedMessage<String, String>(TOPIC, messageNo + "", "appid" + UUID.randomUUID() + "itcast"));        }    }}
public class MyLogPartitioner implements Partitioner {    private static Logger logger = Logger.getLogger(MyLogPartitioner.class);    public MyLogPartitioner(VerifiableProperties props) {    }    /**     *     * @param obj 传来的key 用它来进行hash分到partition     * @param numPartitions 几个partition 如果集群中已存在该topic,那么partition数为原本存在数,否则默认是2     * @return 生产到哪个partition     */    public int partition(Object obj, int numPartitions) { //使用下面被注释掉的代码,则类似于hadoop的partition分发方式,hash取模去发到对应序号的partition,这里使用1则表示发送到orderMQ-1的topic//        return Integer.parseInt(obj.toString())%numPartitions;        return 1;    }}

启动kafka集群,执行main方法,去集群中查看。

[root@mini1 orderMQ-1]# ll总用量 14296-rw-r--r--. 1 root root 10485760 11月 22 07:53 00000000000000000000.index-rw-r--r--. 1 root root 14610099 11月 22 07:53 00000000000000000000.log[root@mini1 orderMQ-1]# ll总用量 14696-rw-r--r--. 1 root root 10485760 11月 22 07:53 00000000000000000000.index-rw-r--r--. 1 root root 15012813 11月 22 07:53 00000000000000000000.log[root@mini1 orderMQ-1]# ll总用量 15184-rw-r--r--. 1 root root 10485760 11月 22 07:53 00000000000000000000.index-rw-r--r--. 1 root root 15513339 11月 22 07:53 00000000000000000000.log[root@mini1 orderMQ-1]# ll总用量 15448-rw-r--r--. 1 root root 10485760 11月 22 07:53 00000000000000000000.index-rw-r--r--. 1 root root 15783297 11月 22 07:53 00000000000000000000.log[root@mini1 orderMQ-1]# ll总用量 16288-rw-r--r--. 1 root root 10485760 11月 22 07:53 00000000000000000000.index-rw-r--r--. 1 root root 16643559 11月 22 07:53 00000000000000000000.log[root@mini1 orderMQ-1]# ll总用量 16600-rw-r--r--. 1 root root 10485760 11月 22 07:53 00000000000000000000.index-rw-r--r--. 1 root root 16961019 11月 22 07:53 00000000000000000000.log

看到消息在不断增加,由于文件内容乱码就不看了。

kafka高性能吞吐
(来源于学习资料自己并不咋懂网络只能去感受了)
kafka实现高性能吞吐主要就是2个原因:1、使用了pageCache,2、使用了sendfile技术

(1)、pageCache是把尽可能多的空闲内存都当做了磁盘缓存来使用,生成的消息大部分存储在缓存中,大数据环境下,生产和消费都是非常快的,那么基本上大部分操作都能同时在缓存中进行,所以吞吐性能高。具体介绍如下:

不同于Redis和MemcacheQ等内存消息队列,Kafka的设计是把所有的Message都要写入速度低容量大的硬盘,以此来换取更强的存储能力。实际上,Kafka使用硬盘并没有带来过多的性能损失,“规规矩矩”的抄了一条“近道”。

首先,说“规规矩矩”是因为Kafka在磁盘上只做Sequence I/O,由于消息系统读写的特殊性,这并不存在什么问题。关于磁盘I/O的性能,引用一组Kafka官方给出的测试数据(Raid-5,7200rpm):

Sequence I/O: 600MB/s
Random I/O: 100KB/s

所以通过只做Sequence I/O的限制,规避了磁盘访问速度低下对性能可能造成的影响。

接下来我们再聊一聊Kafka是如何“抄近道的”。

首先,Kafka重度依赖底层操作系统提供的PageCache功能。当上层有写操作时,操作系统只是将数据写入PageCache,同时标记Page属性为Dirty。

当读操作发生时,先从PageCache中查找,如果发生缺页才进行磁盘调度,最终返回需要的数据。实际上PageCache是把尽可能多的空闲内存都当做了磁盘缓存来使用。同时如果有其他进程申请内存,回收PageCache的代价又很小,所以现代的OS都支持PageCache。

使用PageCache功能同时可以避免在JVM内部缓存数据,JVM为我们提供了强大的GC能力,同时也引入了一些问题不适用与Kafka的设计。

(2)sendfile技术
PageCache还只是第一步,Kafka为了进一步的优化性能还采用了Sendfile技术。在解释Sendfile之前,首先介绍一下传统的网络I/O操作流程,大体上分为以下4步。

OS 从硬盘把数据读到内核区的PageCache。
用户进程把数据从内核区Copy到用户区。
然后用户进程再把数据写入到Socket,数据流入内核区的Socket Buffer上。
OS 再把数据从Buffer中Copy到网卡的Buffer上,这样完成一次发送。
这里写图片描述
整个过程共经历两次Context Switch,四次System Call。同一份数据在内核Buffer与用户Buffer之间重复拷贝,效率低下。其中2、3两步没有必要,完全可以直接在内核区完成数据拷贝。这也正是Sendfile所解决的问题,经过Sendfile优化后,整个I/O过程就变成了下面这个样子。
这里写图片描述
通过以上的介绍不难看出,Kafka的设计初衷是尽一切努力在内存中完成数据交换,无论是对外作为一整个消息系统,或是内部同底层操作系统的交互。如果Producer和Consumer之间生产和消费进度上配合得当,完全可以实现数据交换零I/O。这也就是我为什么说Kafka使用“硬盘”并没有带来过多性能损失的原因。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 怀孕5个月咳嗽有痰怎么办 广州驾照换证体检视力不过怎么办 驾照12分扣完了怎么办费用标准 驾照体检出绿色盲不能补证怎么办 在交警队驾驶员陈述笔录写错怎么办 学驾照做体检把电话填错了怎么办 驾考中心考场停考预约的考试怎么办 口令卡绑定第一次身份证输错怎么办 第一次去医院看病没带身份证怎么办 考科目二紧张怎么办如何消除紧张 考科目三紧张怎么办如何消除紧张 我的驾考准考证和发票丢了怎么办 科目二预约考试下一步点不了怎么办 护士资格证未注册过期没注册怎么办 上海护士延续体检有乙肝携带怎么办 护士资格证从诊所变更到医院怎么办 杭州驾考预约面授没有去怎么办 在外地考的驾驶证丢了怎么办 身份证和驾驶证在外地丢了怎么办 我有摩e照学c1照怎么办 科三网上预约超过了次数限制怎么办 驾照罚款没交过了周期怎么办 驾照考了科科目一想换个驾校怎么办 韩国货物被机场海关扣了怎么办 车管所查不到居住证信息怎么办 高中毕业两年了想考大学怎么办 我买的二手货车营运证是假的怎么办 移民到欧洲国家想去日本怎么办签证 签证要写工作单位如果没有怎么办 办护照时的身份证过期了怎么办 有摩托车驾照想考小车驾照怎么办 分管副局长能直接安排工作吗怎么办 我在北京打工老婆没地方住怎么办 我的车扣了32分怎么办 济南万科地产投诉电话不管用怎么办 买手机被商家欺骗买到合约机怎么办 向消协投诉有用吗?我该怎么办? 我住南开区想办公租房不知怎么办 租房提前退房房东不退押金怎么办 体检时候眼睛有一只是弱视怎么办? b本被扣分9分了怎么办