All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.darkphoenixs.kafka.pool.KafkaMessageReceiverPool Maven / Gradle / Ivy

There is a newer version: 1.5.11
Show newest version
/*
 * Copyright 2015-2016 Dark Phoenixs (Open-Source Organization).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.darkphoenixs.kafka.pool;

import kafka.common.OffsetAndMetadata;
import kafka.common.TopicAndPartition;
import kafka.consumer.ConsumerConfig;
import kafka.consumer.ConsumerIterator;
import kafka.consumer.KafkaStream;
import kafka.javaapi.consumer.ConsumerConnector;
import kafka.message.MessageAndMetadata;
import kafka.serializer.Decoder;
import kafka.serializer.DefaultDecoder;
import kafka.utils.VerifiableProperties;
import org.darkphoenixs.kafka.core.*;
import org.darkphoenixs.mq.exception.MQException;
import org.darkphoenixs.mq.util.RefleTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 

Title: KafkaMessageReceiverPool

*

Description: Kafka消息接受线程池

* * @author Victor.Zxy * @version 1.0 * @since 2015-06-01 */ public class KafkaMessageReceiverPool implements MessageReceiverPool { private static final String tagger = "KafkaMessageReceiverPool"; private static final Logger logger = LoggerFactory .getLogger(KafkaMessageReceiverPool.class); /** * consumer */ protected ConsumerConnector consumer; /** * pool */ protected ExecutorService pool; /** * props */ protected Properties props = new Properties(); /** * The Running. */ protected AtomicBoolean running = new AtomicBoolean(false); /** * messageAdapter */ private KafkaMessageAdapter messageAdapter; /** * destination */ private KafkaDestination destination; /** * poolSize */ private int poolSize; /** * config */ private Resource config; /** * retryCount */ private int retryCount = 3; /** * receiverRetry */ private KafkaMessageReceiverRetry> receiverRetry; /** * keyDecoder */ private Class keyDecoderClass = DefaultDecoder.class; /** * valDecoder */ private Class valDecoderClass = DefaultDecoder.class; /** * threadFactory */ private ThreadFactory threadFactory; /** * Init threadFactory. */ public KafkaMessageReceiverPool() { } /** * @return the threadFactory */ public ThreadFactory getThreadFactory() { return threadFactory; } /** * @param threadFactory the threadFactory to set */ public void setThreadFactory(ThreadFactory threadFactory) { this.threadFactory = threadFactory; } /** * @return the clientId */ public String getClientId() { return props.getProperty(KafkaConstants.CLIENT_ID); } /** * @param clientId the clientId to set */ public void setClientId(String clientId) { props.setProperty(KafkaConstants.CLIENT_ID, clientId); } /** * Gets destination. * * @return the destination */ public KafkaDestination getDestination() { return destination; } /** * Sets destination. * * @param destination the destination */ public void setDestination(KafkaDestination destination) { this.destination = destination; } /** * @return the zookeeperStr */ public String getZookeeperStr() { return props.getProperty(KafkaConstants.ZOOKEEPER_LIST); } /** * @param zookeeperStr the zookeeperStr to set */ public void setZookeeperStr(String zookeeperStr) { props.setProperty(KafkaConstants.ZOOKEEPER_LIST, zookeeperStr); } /** * @return the autoCommit */ public Boolean getAutoCommit() { return Boolean.valueOf(props.getProperty(KafkaConstants.AUTO_COMMIT_ENABLE, "true")); } /** * @param autoCommit the autoCommit to set */ public void setAutoCommit(boolean autoCommit) { props.setProperty(KafkaConstants.AUTO_COMMIT_ENABLE, String.valueOf(autoCommit)); } /** * @return the retryCount */ public int getRetryCount() { return retryCount; } /** * Note: AutoCommit is false to take effect. * * @param retryCount the retryCount to set */ public void setRetryCount(int retryCount) { this.retryCount = retryCount; } /** * @return the props */ public Properties getProps() { return props; } /** * @param props the props to set */ public void setProps(Properties props) { this.props = props; } /** * @return the poolSize */ public int getPoolSize() { return poolSize; } /** * @param poolSize the poolSize to set */ public void setPoolSize(int poolSize) { this.poolSize = poolSize; } /** * @return the config */ public Resource getConfig() { return config; } /** * @param config the config to set */ public void setConfig(Resource config) { this.config = config; try { PropertiesLoaderUtils.fillProperties(props, this.config); } catch (IOException e) { logger.error("Fill properties failed.", e); } } /** * @return the keyDecoderClass */ public Class getKeyDecoderClass() { return keyDecoderClass; } /** * @param keyDecoderClass the keyDecoderClass to set */ public void setKeyDecoderClass(Class keyDecoderClass) { this.keyDecoderClass = keyDecoderClass; } /** * @return the valDecoderClass */ public Class getValDecoderClass() { return valDecoderClass; } /** * @param valDecoderClass the valDecoder to set */ public void setValDecoderClass(Class valDecoderClass) { this.valDecoderClass = valDecoderClass; } /** * @return the messageAdapter */ public KafkaMessageAdapter getMessageAdapter() { return messageAdapter; } /** * @param messageAdapter the messageAdapter to set */ public void setMessageAdapter(KafkaMessageAdapter messageAdapter) { this.messageAdapter = messageAdapter; if (messageAdapter.getDestination() != null) this.setDestination(messageAdapter.getDestination()); } /** * Get a receiver from the pool (just only create a lower-level receiver). * * @return a receiver instance */ @Override public KafkaMessageReceiver getReceiver() { KafkaMessageReceiver receiver = new KafkaMessageReceiverImpl( props, this); return receiver; } /** * Return a receiver back to pool. */ @Override public void returnReceiver(KafkaMessageReceiver receiver) { if (receiver != null) receiver.shutDown(); } @Override public synchronized void init() { String topic = destination.getDestinationName(); int defaultSize = getReceiver().getPartitionCount(topic); if (poolSize == 0 || poolSize > defaultSize) setPoolSize(defaultSize); if (retryCount > 0) receiverRetry = new KafkaMessageReceiverRetry>(topic, retryCount, messageAdapter); this.threadFactory = new KafkaPoolThreadFactory(tagger + "-" + topic); this.pool = Executors.newFixedThreadPool(poolSize, threadFactory); logger.info("Message receiver pool initializing. poolSize : " + poolSize + " config : " + props.toString()); consumer = kafka.consumer.Consumer .createJavaConsumerConnector(new ConsumerConfig(props)); Map topicCountMap = new HashMap(); topicCountMap.put(topic, poolSize); VerifiableProperties verProps = new VerifiableProperties(props); @SuppressWarnings("unchecked") Decoder keyDecoder = (Decoder) RefleTool.newInstance( keyDecoderClass, verProps); @SuppressWarnings("unchecked") Decoder valDecoder = (Decoder) RefleTool.newInstance( valDecoderClass, verProps); Map>> consumerMap = consumer .createMessageStreams(topicCountMap, keyDecoder, valDecoder); List> streams = consumerMap.get(topic); for (final KafkaStream stream : streams) { pool.submit(new ReceiverThread(stream, messageAdapter)); } logger.info("Message receiver pool initialized."); running.set(true); } @Override public synchronized void destroy() { logger.info("Message receiver pool closing."); if (consumer != null) consumer.shutdown(); if (pool != null) { pool.shutdown(); try { if (!pool.awaitTermination(KafkaConstants.INIT_TIMEOUT_MS, TimeUnit.MILLISECONDS)) { logger.warn("Timed out waiting for consumer threads to shut down, exiting uncleanly"); } } catch (InterruptedException e) { logger.error("Interrupted during shutdown, exiting uncleanly"); } } if (receiverRetry != null) receiverRetry.destroy(); logger.info("Message receiver pool closed."); running.set(false); } @Override public synchronized boolean isRunning() { return running.get(); } /** * Receiver thread to receive message. */ class ReceiverThread implements Runnable { private KafkaStream stream; private KafkaMessageAdapter adapter; public ReceiverThread(KafkaStream stream, KafkaMessageAdapter adapter) { this.stream = stream; this.adapter = adapter; } @Override public void run() { logger.info(Thread.currentThread().getName() + " clientId: " + stream.clientId() + " start."); ConsumerIterator it = stream.iterator(); while (it.hasNext()) { MessageAndMetadata messageAndMetadata = it.next(); try { this.adapter.messageAdapter(messageAndMetadata); } catch (MQException e) { if (receiverRetry != null) receiverRetry.receiveMessageRetry(messageAndMetadata); logger.error("Receive message failed." + " topic: " + messageAndMetadata.topic() + " offset: " + messageAndMetadata.offset() + " partition: " + messageAndMetadata.partition(), e); } finally { /* commitOffsets */ if (!getAutoCommit()) { consumer.commitOffsets(Collections.singletonMap( TopicAndPartition.apply(messageAndMetadata.topic(), messageAndMetadata.partition()), OffsetAndMetadata.apply(messageAndMetadata.offset() + 1)), true); } } } logger.info(Thread.currentThread().getName() + " clientId: " + stream.clientId() + " end."); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy