问题导读

1.Kafka如何实现和Consumer之间的交互?
2.使用SimpleConsumer有哪些弊端呢?

1.Kafka提供了两套API给Consumer

  • The high-level Consumer API
  • The SimpleConsumer API

第一种高度抽象的Consumer API,它使用起来简单、方便,但是对于某些特殊的需求我们可能要用到第二种更底层的API,那么先介绍下第二种API能够帮助我们做哪些事情

  • 一个消息读取多次
  • 在一个处理过程中只消费Partition其中的一部分消息
  • 添加事务管理机制以保证消息被处理且仅被处理一次

2.使用SimpleConsumer有哪些弊端呢?

  • 必须在程序中跟踪offset值
  • 必须找出指定Topic Partition中的lead broker
  • 必须处理broker的变动

3.使用SimpleConsumer的步骤

  • 从所有活跃的broker中找出哪个是指定Topic Partition中的leader broker
  • 找出指定Topic Partition中的所有备份broker
  • 构造请求
  • 发送请求查询数据
  • 处理leader broker变更

4.代码实例

  1. package bonree.consumer;
  2. import java.nio.ByteBuffer;
  3. import java.util.ArrayList;
  4. import java.util.Collections;
  5. import java.util.HashMap;
  6. import java.util.List;
  7. import java.util.Map;
  8. import kafka.api.FetchRequest;
  9. import kafka.api.FetchRequestBuilder;
  10. import kafka.api.PartitionOffsetRequestInfo;
  11. import kafka.common.ErrorMapping;
  12. import kafka.common.TopicAndPartition;
  13. import kafka.javaapi.FetchResponse;
  14. import kafka.javaapi.OffsetResponse;
  15. import kafka.javaapi.PartitionMetadata;
  16. import kafka.javaapi.TopicMetadata;
  17. import kafka.javaapi.TopicMetadataRequest;
  18. import kafka.javaapi.consumer.SimpleConsumer;
  19. import kafka.message.MessageAndOffset;
  20. public class SimpleExample {
  21. private List<String> m_replicaBrokers = new ArrayList<String>();
  22. public SimpleExample() {
  23. m_replicaBrokers = new ArrayList<String>();
  24. }
  25. public static void main(String args[]) {
  26. SimpleExample example = new SimpleExample();
  27. // 最大读取消息数量
  28. long maxReads = Long.parseLong("3");
  29. // 要订阅的topic
  30. String topic = "mytopic";
  31. // 要查找的分区
  32. int partition = Integer.parseInt("0");
  33. // broker节点的ip
  34. List<String> seeds = new ArrayList<String>();
  35. seeds.add("192.168.4.30");
  36. seeds.add("192.168.4.31");
  37. seeds.add("192.168.4.32");
  38. // 端口
  39. int port = Integer.parseInt("9092");
  40. try {
  41. example.run(maxReads, topic, partition, seeds, port);
  42. } catch (Exception e) {
  43. System.out.println("Oops:" + e);
  44. e.printStackTrace();
  45. }
  46. }
  47. public void run(long a_maxReads, String a_topic, int a_partition, List<String> a_seedBrokers, int a_port) throws Exception {
  48. // 获取指定Topic partition的元数据
  49. PartitionMetadata metadata = findLeader(a_seedBrokers, a_port, a_topic, a_partition);
  50. if (metadata == null) {
  51. System.out.println("Can't find metadata for Topic and Partition. Exiting");
  52. return;
  53. }
  54. if (metadata.leader() == null) {
  55. System.out.println("Can't find Leader for Topic and Partition. Exiting");
  56. return;
  57. }
  58. String leadBroker = metadata.leader().host();
  59. String clientName = "Client_" + a_topic + "_" + a_partition;
  60. SimpleConsumer consumer = new SimpleConsumer(leadBroker, a_port, 100000, 64 * 1024, clientName);
  61. long readOffset = getLastOffset(consumer, a_topic, a_partition, kafka.api.OffsetRequest.EarliestTime(), clientName);
  62. int numErrors = 0;
  63. while (a_maxReads > 0) {
  64. if (consumer == null) {
  65. consumer = new SimpleConsumer(leadBroker, a_port, 100000, 64 * 1024, clientName);
  66. }
  67. FetchRequest req = new FetchRequestBuilder().clientId(clientName).addFetch(a_topic, a_partition, readOffset, 100000).build();
  68. FetchResponse fetchResponse = consumer.fetch(req);
  69. if (fetchResponse.hasError()) {
  70. numErrors++;
  71. // Something went wrong!
  72. short code = fetchResponse.errorCode(a_topic, a_partition);
  73. System.out.println("Error fetching data from the Broker:" + leadBroker + " Reason: " + code);
  74. if (numErrors > 5)
  75. break;
  76. if (code == ErrorMapping.OffsetOutOfRangeCode()) {
  77. // We asked for an invalid offset. For simple case ask for
  78. // the last element to reset
  79. readOffset = getLastOffset(consumer, a_topic, a_partition, kafka.api.OffsetRequest.LatestTime(), clientName);
  80. continue;
  81. }
  82. consumer.close();
  83. consumer = null;
  84. leadBroker = findNewLeader(leadBroker, a_topic, a_partition, a_port);
  85. continue;
  86. }
  87. numErrors = 0;
  88. long numRead = 0;
  89. for (MessageAndOffset messageAndOffset : fetchResponse.messageSet(a_topic, a_partition)) {
  90. long currentOffset = messageAndOffset.offset();
  91. if (currentOffset < readOffset) {
  92. System.out.println("Found an old offset: " + currentOffset + " Expecting: " + readOffset);
  93. continue;
  94. }
  95. readOffset = messageAndOffset.nextOffset();
  96. ByteBuffer payload = messageAndOffset.message().payload();
  97. byte[] bytes = new byte[payload.limit()];
  98. payload.get(bytes);
  99. System.out.println(String.valueOf(messageAndOffset.offset()) + ": " + new String(bytes, "UTF-8"));
  100. numRead++;
  101. a_maxReads--;
  102. }
  103. if (numRead == 0) {
  104. try {
  105. Thread.sleep(1000);
  106. } catch (InterruptedException ie) {
  107. }
  108. }
  109. }
  110. if (consumer != null)
  111. consumer.close();
  112. }
  113. public static long getLastOffset(SimpleConsumer consumer, String topic, int partition, long whichTime, String clientName) {
  114. TopicAndPartition topicAndPartition = new TopicAndPartition(topic, partition);
  115. Map<TopicAndPartition, PartitionOffsetRequestInfo> requestInfo = new HashMap<TopicAndPartition, PartitionOffsetRequestInfo>();
  116. requestInfo.put(topicAndPartition, new PartitionOffsetRequestInfo(whichTime, 1));
  117. kafka.javaapi.OffsetRequest request = new kafka.javaapi.OffsetRequest(requestInfo, kafka.api.OffsetRequest.CurrentVersion(), clientName);
  118. OffsetResponse response = consumer.getOffsetsBefore(request);
  119. if (response.hasError()) {
  120. System.out.println("Error fetching data Offset Data the Broker. Reason: " + response.errorCode(topic, partition));
  121. return 0;
  122. }
  123. long[] offsets = response.offsets(topic, partition);
  124. return offsets[0];
  125. }
  126. /**
  127. * @param a_oldLeader
  128. * @param a_topic
  129. * @param a_partition
  130. * @param a_port
  131. * @return String
  132. * @throws Exception
  133. *             找一个leader broker
  134. */
  135. private String findNewLeader(String a_oldLeader, String a_topic, int a_partition, int a_port) throws Exception {
  136. for (int i = 0; i < 3; i++) {
  137. boolean goToSleep = false;
  138. PartitionMetadata metadata = findLeader(m_replicaBrokers, a_port, a_topic, a_partition);
  139. if (metadata == null) {
  140. goToSleep = true;
  141. } else if (metadata.leader() == null) {
  142. goToSleep = true;
  143. } else if (a_oldLeader.equalsIgnoreCase(metadata.leader().host()) && i == 0) {
  144. // first time through if the leader hasn't changed give
  145. // ZooKeeper a second to recover
  146. // second time, assume the broker did recover before failover,
  147. // or it was a non-Broker issue
  148. //
  149. goToSleep = true;
  150. } else {
  151. return metadata.leader().host();
  152. }
  153. if (goToSleep) {
  154. try {
  155. Thread.sleep(1000);
  156. } catch (InterruptedException ie) {
  157. }
  158. }
  159. }
  160. System.out.println("Unable to find new leader after Broker failure. Exiting");
  161. throw new Exception("Unable to find new leader after Broker failure. Exiting");
  162. }
  163. private PartitionMetadata findLeader(List<String> a_seedBrokers, int a_port, String a_topic, int a_partition) {
  164. PartitionMetadata returnMetaData = null;
  165. loop: for (String seed : a_seedBrokers) {
  166. SimpleConsumer consumer = null;
  167. try {
  168. consumer = new SimpleConsumer(seed, a_port, 100000, 64 * 1024, "leaderLookup");
  169. List<String> topics = Collections.singletonList(a_topic);
  170. TopicMetadataRequest req = new TopicMetadataRequest(topics);
  171. kafka.javaapi.TopicMetadataResponse resp = consumer.send(req);
  172. List<TopicMetadata> metaData = resp.topicsMetadata();
  173. for (TopicMetadata item : metaData) {
  174. for (PartitionMetadata part : item.partitionsMetadata()) {
  175. if (part.partitionId() == a_partition) {
  176. returnMetaData = part;
  177. break loop;
  178. }
  179. }
  180. }
  181. } catch (Exception e) {
  182. System.out.println("Error communicating with Broker [" + seed + "] to find Leader for [" + a_topic + ", " + a_partition + "] Reason: " + e);
  183. } finally {
  184. if (consumer != null)
  185. consumer.close();
  186. }
  187. }
  188. if (returnMetaData != null) {
  189. m_replicaBrokers.clear();
  190. for (kafka.cluster.Broker replica : returnMetaData.replicas()) {
  191. m_replicaBrokers.add(replica.host());
  192. }
  193. }
  194. return returnMetaData;
  195. }
  196. }

转自:http://www.aboutyun.com/thread-11117-1-1.html

Kafka详解五:Kafka Consumer的底层API- SimpleConsumer的更多相关文章

  1. kafka详解(一)--kafka是什么及怎么用

    kafka是什么 在回答这个问题之前,我们需要先了解另一个东西--event streaming. 什么是event streaming 我觉得,event streaming 是一个动态的概念,它描 ...

  2. kafka详解(二)--kafka为什么快

    前言 Kafka 有多快呢?我们可以使用 OpenMessaging Benchmark Framework 测试框架方便地对 RocketMQ.Pulsar.Kafka.RabbitMQ 等消息系统 ...

  3. .NET DLL 保护措施详解(五)常规条件下的破解

    为了证实在常规手段破解下能有效保护程序核心功能(演示版本对AES加解密算法及数据库的密钥(一段字符串)进行了保护),特对此DLL保护思路进行相应的测试,包含了反编译及反射测试,看是否能得到AES加解密 ...

  4. 转:Windows下的PHP开发环境搭建——PHP线程安全与非线程安全、Apache版本选择,及详解五种运行模式。

    原文来自于:http://www.ituring.com.cn/article/128439 Windows下的PHP开发环境搭建——PHP线程安全与非线程安全.Apache版本选择,及详解五种运行模 ...

  5. python设计模式之迭代器与生成器详解(五)

    前言 迭代器是设计模式中的一种行为模式,它提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示.python提倡使用生成器,生成器也是迭代器的一种. 系列文章 python设计模 ...

  6. pika详解(五)登录认证及connectionParameters

    pika详解(五)登录认证及connectionParameters 本文链接:https://blog.csdn.net/comprel/article/details/94662916 版权 pi ...

  7. [转]人人网首页拖拽上传详解(HTML5 Drag&Drop、FileReader API、formdata)

    人人网首页拖拽上传详解(HTML5 Drag&Drop.FileReader API.formdata) 2011年12月11日 | 彬Go 上一篇:给力的 Google HTML5 训练营( ...

  8. 详解Java8的日期和时间API

    详解Java8的日期和时间API 在JDK1.0的时候,Java引入了java.util.Date来处理日期和时间:在JDK1.1的时候又引入了功能更强大的java.util.Calendar,但是C ...

  9. Kafka详解与总结(五)

    Kafka持久化 1. 概述 Kafka大量依赖文件系统去存储和缓存消息.对于硬盘有个传统的观念是硬盘总是很慢,这使很多人怀疑基于文件系统的架构能否提供优异的性能.实际上硬盘的快慢完全取决于使用它的方 ...

随机推荐

  1. 第一次打开Pycharm如何操作?

    1.第一次打开pycharm的界面: 2.一些pycharm的选择: 3.上一步,红字4的位置,点击进去,对下面界面进行选择,也就是选择System Interpreter解释器,然后对Interpr ...

  2. JS 插件 fastclick.js 解决手机端click点击延迟

    FastClick 是一个简单,易于使用的JS库用于消除在移动浏览器上触发click事件与一个物理Tap(敲击)之间的300延迟. 对于非移动浏览器不启作用,禁用缩放标签. <meta name ...

  3. General Decimal Arithmetic 浮点算法

    General Decimal Arithmetic http://speleotrove.com/decimal/ General Decimal Arithmetic [ FAQ | Decima ...

  4. 是面向对象设计五个基本原则(SOLID)

    单一职责原则 - 搜狗百科 https://baike.sogou.com/v51360965.htm 单一职责原则并不是一个孤立的面向对象设计原则,它是面向对象设计五个基本原则(SOLID)之一.这 ...

  5. ES6学习笔记(三)——数值的扩展

    看到这条条目录有没有感觉很枯燥,觉得自己的工作中还用不到它所以实在没有耐心看下去,我也是最近得闲,逼自己静下心来去学习去总结,只有在别人浮躁的时候你能静下心来去学去看去总结,你才能进步.毕竟作为前端不 ...

  6. MySQL中行锁的算法

    行锁的3中算法 Record Lock:单个行记录上的锁 Gap Lock:间隙锁,锁定一个范围,但不包含记录本身 Next-key Lock:Gap Lock+Record Lock锁定一个范围,并 ...

  7. javaweb action无法跳转、表单无法跳转的解决方法

    action无法跳转,表单无法跳转的解决方法 刚在网上搜索了一下,发现我的这篇文章已被非常多人转载了去其他站点.暗爽,只是还是希望大家注明出处. 顺便说明一下.下面是在struts2中通过測试的 ac ...

  8. hadoop学习第三天-MapReduce介绍&&WordCount示例&&倒排索引示例

    一.MapReduce介绍 (最好以下面的两个示例来理解原理) 1. MapReduce的基本思想 Map-reduce的思想就是“分而治之” Map Mapper负责“分”,即把复杂的任务分解为若干 ...

  9. 剑指offer 面试17题

    面试17题: 题目:打印从1到最大的n位数 题:输入数字n,按顺序打印出从1到最大的n位十进制数,比如输入3,则打印出1.2.3一直到最大的3位数999. 解题思路:需要考虑大数问题,这是题目设置的陷 ...

  10. 如何用好 Google 等搜索引擎

    1: 双引号短语搜索2: 减号减号前面必须是空格,减号后面没有空格,紧跟着需要排除的词例如:搜索 -引擎返回的则是包含“搜索”这个词,却不包含“引擎”这个词的结果3: 星号RE,通配符4: intit ...