软件测试学习交流群:925205234提纲关于KafkaKafka基础Kafka的原理配置以及实现软件测试学习交流群:925205234关于kafka什么是Kafka?Kafka的产生软件测试学习交流群:925205234什么是kafka?ApacheKafka是一个分布式消息发布订阅系统。它最初由LinkedIn(领英)公司基于独特的设计实现为一个分布式的提交日志系统(adistributedcommitlog),之后成为Apache项目的一部分。软件测试学习交流群:925205234Kafka的产生 Kafka的设计初衷是希望作为一个统一的平台,来处理一家大公司可能有的所有实时数据。要做到这一点,我们不得不思考一个相当广泛的用例。它必须具有高吞吐量,以支持大容量的事件流,如实时日志聚集。它将需要优雅地处理大型数据积压,要能够支持从脱机系统的周期性数据负载。我们想要支持以分区,分布式的,实时处理来这些创建新派生的feeds,促使我们的分区和消费模式。最后,在消息被送入其他数据系统的情况下,我们的新的系统必须能够保证在机器故障存在的容错。软件测试学习交流群:925205234Kafka的特性快速 单个Kafka服务每秒可以处理数以千计从客户端发来的几百兆字节的读取和写入。可扩展性 Kafka被设计为允许单个集群作为中央数据骨干大型组织。它可以弹性地,透明地扩展,且无需停机。数据流被划分并分布在机器的集群中,允许数据流比任何单一机器的性能大,并让集群来协调消费者。可靠性 Kafka使用现代化的集群为中心消息被保存在磁盘上,并在集群中复制,防止数据丢失。每个代理可以处理TB级的消息,而不影响性能。分布式设计 Kafka使用现代化的集群为中心设计,并提供了强大的耐用性和容错性保证。软件测试学习交流群:925205234Kafka的基本术语Topic Kafka将消息种子(Feed)分门别类,每一类的消息称之为话题(Topic).Producer发布消息的对象称之为话题生产者(Kafkatopicproducer)Consumer订阅消息并处理发布的消息的种子的对象称之为话题消费者(consumers)Broker已发布的消息保存在一组服务器中,称之为Kafka集群。集群中的每一个服务器都是一个代理(Broker).消费者可以订阅一个或多个话题,并从Broker拉数据,从而消费这些已发布的消息。软件测试学习交流群:925205234Kafka集群让我们站的高一点,从高的角度来看,Kafka集群的业务处理就像这样子:Client和Server之间的交流通过一条简单、高性能并且不局限某种开发语言的TCP协议。除了JavaClient外,还有很多其他编程语言。软件测试学习交流群:925205234话题话题和日志和日志(Topic和和Log)更深入的了解一下Kafka中的Topic。Topic是发布的消息的类别或者种子Feed名。对于每一个Topic,Kafka集群维护这一个分区的log,就像下图中的示例:软件测试学习交流群:925205234话题话题和日志和日志(Topic和和Log)每一个分区都是一个顺序的、不可变的消息队列,并且可以持续的添加。分区中的消息都被分配了一个序列号,称之为偏移量(offset),在每个分区中此偏移是唯一的。Kafka集群保持所有的消息,直到它们过期,无论消息是否被消费了。实际上消费者所持有的仅有的元数据就是这个偏移量,也就是消费者在这个log中的位置。这个偏移量由消费者控制:正常情况当消费者消费消息的时候,偏移量也线性的的增加。但是实际偏移量由消费者控制,消费者可以将偏移量重置为更老的一个偏移 量,重新读取消息。可以看到这种设计对消费者来说操作自如,一个消费者的操作不会影响其它消费者对此log的处理。Kafka中采用分区的设计有几个目的。一是可以处理更多的消息,不受单台服务器的限制。Topic拥有多个分区意味着它可以不受限的处理更多的数据。第二,分区可以作为并行处理的单元。软件测试学习交流群:925205234分布式分布式(Distribution)Log的分区被分布到集群中的多个服务器上。每个服务器处理它分到的分区。根据配置每个分区还可以复制到其它服务器作为备份容错。每个分区有一个leader,零或多个follower。Leader处理此分区的所有的读写请求,而follower被动的复制数据。如果leader宕机,其它的一个follower会被推举为新的leader。一台服务器可能同时是一个分区的leader,另一个分区的follower。这样可以平衡负载,避免所有的请求都只让一台或者某几台服务器处理。软件测试学习交流群:925205234生生产产者者(Producers)生产者往某个Topic上发布消息。生产者也负责选择发布到这此Topic上的哪一个分区。最简单的方式从分区列表中轮流选择。也可以根据某种算法依照权重选择分区。开发者负责如何选择分区的算法。软件测试学习交流群:925205234消消费费者者(Consumers)通常来讲,消息模型可以分为两种,队列(queue)和发布-订阅式。队列的处理方式是 一组消费者从服务器读取消息,一条消息只有其中的一个消费者来处理。在发布-订阅模型中,消息被广播给所有的消费者,接收到消息的消费者都可以处理此消息。Kafka为这两种模型提供了单一的消费者抽象模型:消费者组(consumergroup)。消费者用一个消费者组名标记自己。一个发布在Topic上消息被分发给此消费者组中的一个消费者。假如所有的消费者都在一个组中,那么这就变成了queue模型。假如所有的消费者都在不同的组中,那么就完全变成了发布-订阅模型。通俗一点,我们可以创建一些消费者组作为逻辑上的订阅者。每个组包含数目不等的消费者,一个组内多个消费者可以用来扩展性能和容错。如下图所示:软件测试学习交流群:925205234消消费费者者(Consumers)Kafka的2个服务器集群管理4个分区(p0-p3)2个消费组,消费者A组有2个消费实例,消费者B组有4个消费实例。软件测试学习交流群:925205234消消费费者者(Consumers)正像传统的消息系统一样,Kafka保证消息的顺序不变。传统的队列模型保持消息,并且保证它们的先后顺序不变。但是,尽管服务器保证了消息的顺序,消息还是异步的发送给各个消费者,消费者收到消息的先后顺序不能保证了。这也意味着并行消费将不能保证消息的先后顺序。用过 传统的消息系统的同学肯定清楚,消息的顺序处理很让人头痛。如果只让一个消费者处理消息,又违背了并行处理的初衷。在这一点上Kafka做的更好,尽管并没有完全解决上述问题。Kafka采用了一种分而治之的策略:分区。因为Topic分区中消息只能由消费者组中的唯一一个消费者处理,所以消息肯定是按照先后顺序进行处理的。但是它也仅仅是保证Topic的一个分区顺序处 理,不能保证跨分区的消息先后处理顺序。所以,如果你想要顺序的处理Topic的所有消息,那就只提供一个分区。软件测试学习交流群:925205234Kafka的保证(Guarantees)生产者发送到一个特定的Topic的分区上的消息将会按照它们发送的顺序依次加入消费者收到的消息也是此顺序如果一个Topic配置了复制因子(replicationfacto)为N,那么可以允许N-1服务器宕掉而不丢失任何已经增加的消息软件测试学习交流群:925205234Kafka的原理持久性生产者消费者消息传送机制复制备份日志分配Zookeeper与Kafka软件测试学习交流群:925205234持久性持久性Kafka的存储布局非常简单。话题的每个分区对应一个逻辑日志。物理上,一个日志为相同大小的一组分段文件。每次生产者发布消息到一个分区,代理就将消息追加到最后一个段文件中。同时为了减少磁盘写入的次数,broker会将消息暂时buffer起来,当消息的个数(或尺寸)达到一定阀值时,再flush到磁盘,这样减少了磁盘IO调用的次数.软件测试学习交流群:925205234生生产产者者负载均衡:producer将会和Topic下所有partitionleader保持socket连接;消息由producer直接通过socket发送到broker,中间不会经过任何“路由层”。事实上,消息被路由到 哪个partition上,有producer客户端决定。比如可以采用“random”,“key-hash”“轮询”等,如果一个topic中有多个 partitions,那么在producer端实现消息均衡分发是必要的.其中partitionleader的位置(host:port)注册在zookeeper中,producer作为zookeeperclient,已经注册了watch用来监听partitionleader的变更事件.异步发送:将多条消息暂且在客户端buffer起来,并将他们批量的发送到broker,小数据IO太多,会拖慢整体的网络延迟,批量延迟发送事实上提升了网络效率。不过这也有一定的隐患,比如说当producer失效时,那些尚未发送的消息将会丢失。软件测试学习交流群:925205234消消费费者者consumer端向broker发送“fetch”请求,并告知其获取消息的offset;此后consumer将会获得一定条数的消息;consumer端也可以重置offset来重新消费消息.在 JMS实现中,Topic模型基于push方式,即broker将消息推送给consumer端。不过在kafka中,采用了pull方式,即 consumer在和broker建立连接之后,主动去pull(或者说fetch)消息;这种模式有些优点,首先consumer端可以根据自己的消费能力适时的去fetch消息并处理,且可以控制消息消费的进度(offset);此外,消费者可以良好的控制消息消费的数量。其他JMS实现,消息消费的位置是有prodiver保留,以便避免重复发送消息或者将没有消费成功的消息重发等,同时还要控制消息的状态。这就要求JMSbroker需要太多额外的工作.在kafka中,partition中的消息只有一个consumer在消费,且不存在消息状态的控制,也没有复杂的消息确认机制,可见kafkabroker端是相当轻量级的.当消息被consumer接收之后,consumer可以在本地保存最后消息的offset,并间歇性的向 zookeeper注册offset.由此可见,consumer客户端也很轻量级.软件测试学习交流群:925205234消息消息传传送机制送机制对于JMS实现,消息传输担保非常直接:有且只有一次(exactlyonce).在kafka中稍有不同:1)atmostonce:最多一次,这个和JMS中非持久化消息类似.发送一次,无论成败,将不会重发.2)atleastonce:消息至少发送一次,如果消息未能接受成功,可能会重发,直到接收成功。3)exactlyonce:消息只会发送一次。atmostonce:消费者fetch消息,然后保存offset,然后处理消息;当client保存offset之后,但是在消息处理过程中出现了异常,导致部分消息未能继续处理.那么此后未处理的消息将不能被fetch到,这就是atmostonce.atleastonce:消费者fetch消息,然后处理消息,然后保存offset.如果消息处理成功之后,但是在保存offset阶段zookeeper异常导致保存操作未能执行成功,这就导致接下来再次fetch时可能获得上次已经处理过的消息,这就是atleastonce,原因offset没有及时的提交给zookeeper,zookeeper恢复正常还是之前offset状态.exactlyonce:kafka中并没有严格的去实现(基于2阶段提交,事务),我们认为这种策略在kafka中是没有必要的.通常情况下at-least-once是我们首选.(相比atmosto