我正在尝试向kafka消费者获取生成并发布到Java主题的消息。我的消费者如下。
consumer.java
$needle= $_GET["singleid"];
$collection = Mage::getModel('catalog/product')->getCollection()->addAttributeToFilter('name', array(
array('like' => '% '.$needle.' %'), //spaces on each side
array('like' => '% '.$needle), //space before and ends with $needle
array('like' => $needle.' %') // starts with needle and space after
));
$collection->addAttributeToSelect('name', 'entity_id', 'price');
foreach ($collection as $_product){
echo $_product->getId().'</br>';
echo $_product->getName().'</br>';
echo $_product->getProductUrl().'</br>';//getting this only
echo $_product->getPrice().'</br>';
}
当我运行上面的代码时,我在控制台中什么也得不到,因为屏幕后面的java生产者程序在“AATest”主题下不断发布数据。在zookeeper控制台中,当我尝试运行上面的consumer.java
时,我得到以下几行import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import kafka.consumer.Consumer;
import kafka.consumer.ConsumerConfig;
import kafka.consumer.ConsumerIterator;
import kafka.consumer.KafkaStream;
import kafka.javaapi.consumer.ConsumerConnector;
import kafka.javaapi.message.ByteBufferMessageSet;
import kafka.message.MessageAndOffset;
public class KafkaConsumer extends Thread {
final static String clientId = "SimpleConsumerDemoClient";
final static String TOPIC = " AATest";
ConsumerConnector consumerConnector;
public static void main(String[] argv) throws UnsupportedEncodingException {
KafkaConsumer KafkaConsumer = new KafkaConsumer();
KafkaConsumer.start();
}
public KafkaConsumer(){
Properties properties = new Properties();
properties.put("zookeeper.connect","10.200.208.59:2181");
properties.put("group.id","test-group");
ConsumerConfig consumerConfig = new ConsumerConfig(properties);
consumerConnector = Consumer.createJavaConsumerConnector(consumerConfig);
}
@Override
public void run() {
Map<String, Integer> topicCountMap = new HashMap<String, Integer>();
topicCountMap.put(TOPIC, new Integer(1));
Map<String, List<KafkaStream<byte[], byte[]>>> consumerMap = consumerConnector.createMessageStreams(topicCountMap);
KafkaStream<byte[], byte[]> stream = consumerMap.get(TOPIC).get(0);
System.out.println(stream);
ConsumerIterator<byte[], byte[]> it = stream.iterator();
while(it.hasNext())
System.out.println("from it");
System.out.println(new String(it.next().message()));
}
private static void printMessages(ByteBufferMessageSet messageSet) throws UnsupportedEncodingException {
for(MessageAndOffset messageAndOffset: messageSet) {
ByteBuffer payload = messageAndOffset.message().payload();
byte[] bytes = new byte[payload.limit()];
payload.get(bytes);
System.out.println(new String(bytes, "UTF-8"));
}
}
}
当我运行一个指向AATest主题的单独控制台消费者时,我将生成器生成的所有数据都提供给该主题。
消费者和经纪人都在同一台机器上,而生产者在不同的机器上。这实际上类似于this question。但是通过它来帮助我。请帮帮我。
答案 0 :(得分:1)
不同的答案,但在我的情况下恰好是消费者的初始偏移量(auto.offset.reset
)。因此,设置auto.offset.reset=earliest
修复了我的方案中的问题。这是因为我首先发布事件然后开始消费者。
默认情况下,消费者仅使用在启动后发布的事件,因为默认情况下为auto.offset.reset=latest
。
例如。 consumer.properties
bootstrap.servers=localhost:9092
enable.auto.commit=true
auto.commit.interval.ms=1000
session.timeout.ms=30000
auto.offset.reset=earliest
key.deserializer=org.apache.kafka.common.serialization.StringDeserializer
value.deserializer=org.apache.kafka.common.serialization.StringDeserializer
class KafkaEventConsumerSpecs extends FunSuite {
case class TestEvent(eventOffset: Long, hashValue: Long, created: Date, testField: String) extends BaseEvent
test("given an event in the event-store, consumes an event") {
EmbeddedKafka.start()
//PRODUCE
val event = TestEvent(0l, 0l, new Date(), "data")
val config = new Properties() {
{
load(this.getClass.getResourceAsStream("/producer.properties"))
}
}
val producer = new KafkaProducer[String, String](config)
val persistedEvent = producer.send(new ProducerRecord(event.getClass.getSimpleName, event.toString))
assert(persistedEvent.get().offset() == 0)
assert(persistedEvent.get().checksum() != 0)
//CONSUME
val consumerConfig = new Properties() {
{
load(this.getClass.getResourceAsStream("/consumer.properties"))
put("group.id", "consumers_testEventsGroup")
put("client.id", "testEventConsumer")
}
}
assert(consumerConfig.getProperty("group.id") == "consumers_testEventsGroup")
val kafkaConsumer = new KafkaConsumer[String, String](consumerConfig)
assert(kafkaConsumer.listTopics().asScala.map(_._1).toList == List("TestEvent"))
kafkaConsumer.subscribe(Collections.singletonList("TestEvent"))
val events = kafkaConsumer.poll(1000)
assert(events.count() == 1)
EmbeddedKafka.stop()
}
}
但是,如果首先启动消费者然后发布消费者,则消费者应该能够使用不需要将auto.offset.reset
设置为earliest
的事件。
答案 1 :(得分:1)
在我们的案例中,我们通过以下步骤解决了我们的问题:
我们发现的第一件事就是有一个名为“重试”的配置。对于KafkaProducer及其默认值意味着“没有重试”。此外,KafkaProducer的send方法是异步的,而不调用send方法的get方法的结果。这样,无法保证将生成的消息传递给相应的代理而不重试。所以,你必须增加一点,或者可以使用KafkaProducer的幂等或事务模式。
第二个案例是关于Kafka和Zookeeper的版本。我们选择了1.0.0版本的Kafka和Zookeeper 3.4.4。特别是,Kafka 1.0.0存在与Zookeeper连接的问题。如果Kafka在与意外的异常情况下失去与Zookeeper的连接,它将失去尚未同步的分区的领导权。有关此问题的错误主题: https://issues.apache.org/jira/browse/KAFKA-2729 在我们在Kafka日志中找到相应的日志后,我们将Kafka代理版本升级到1.1.0。
同样重要的是要注意小尺寸的分区(如100或更少)会增加生产者的吞吐量,因此如果没有足够的消费者,那么可用的消费者就会陷入延迟消息的结果中。我们用分钟测量延迟,大约10-15分钟)。因此,您需要根据可用资源正确平衡和配置应用程序的分区大小和线程数。
答案 2 :(得分:0)
在将新使用者添加到相同的组ID时,kafka可能还会花费很长时间重新平衡使用者组。 检查kafka日志以查看启动消费者后组是否重新平衡