2016-07-25 14:44:02 -07:00
|
|
|
/**
|
|
|
|
* Copyright 2015 LinkedIn Corp. All rights reserved.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
2016-10-11 11:26:36 -07:00
|
|
|
package models.kafka;
|
2016-07-25 14:44:02 -07:00
|
|
|
|
2016-08-04 13:07:19 -07:00
|
|
|
import java.lang.reflect.Method;
|
2016-07-25 14:44:02 -07:00
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Properties;
|
2016-08-04 13:07:19 -07:00
|
|
|
import kafka.javaapi.consumer.ConsumerConnector;
|
2016-07-26 12:16:34 -07:00
|
|
|
import metadata.etl.models.EtlJobName;
|
|
|
|
import models.daos.EtlJobPropertyDao;
|
2016-08-04 13:07:19 -07:00
|
|
|
import org.apache.avro.generic.GenericData;
|
2016-08-03 18:55:07 -07:00
|
|
|
import play.Logger;
|
2016-10-11 11:26:36 -07:00
|
|
|
import utils.JdbcUtil;
|
2016-08-04 13:07:19 -07:00
|
|
|
import wherehows.common.kafka.schemaregistry.client.SchemaRegistryClient;
|
|
|
|
import wherehows.common.writers.DatabaseWriter;
|
2016-07-25 14:44:02 -07:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Utilities for Kafka configurations and topics
|
|
|
|
*/
|
|
|
|
public class KafkaConfig {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Class for storing Kafka Topic info
|
|
|
|
*/
|
|
|
|
public static class Topic {
|
|
|
|
public String topic;
|
|
|
|
public int numOfWorkers; // number of kafka consumer workers
|
|
|
|
public String processor; // processor class to invoke
|
|
|
|
public String dbTable; // Database table to write to
|
|
|
|
|
|
|
|
Topic(String topic, int numOfWorkers, String processor, String dbTable) {
|
|
|
|
this.topic = topic;
|
|
|
|
this.numOfWorkers = numOfWorkers;
|
|
|
|
this.processor = processor;
|
|
|
|
this.dbTable = dbTable;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-04 13:07:19 -07:00
|
|
|
private final Properties _props = new Properties();
|
|
|
|
// Map of <topic_name, topic_content>
|
|
|
|
private final Map<String, Topic> _topics = new HashMap<>();
|
|
|
|
private final Map<String, Object> _topicProcessorClass = new HashMap<>();
|
|
|
|
private final Map<String, Method> _topicProcessorMethod = new HashMap<>();
|
|
|
|
private final Map<String, DatabaseWriter> _topicDbWriter = new HashMap<>();
|
|
|
|
|
|
|
|
private ConsumerConnector _consumer;
|
|
|
|
private SchemaRegistryClient _schemaRegistryClient;
|
|
|
|
|
2016-07-25 14:44:02 -07:00
|
|
|
/**
|
2016-08-04 13:07:19 -07:00
|
|
|
* Update Kafka properties and topics from wh_etl_job_properties table
|
2016-07-25 14:44:02 -07:00
|
|
|
* @throws Exception
|
|
|
|
*/
|
2016-08-04 13:07:19 -07:00
|
|
|
public void updateKafkaProperties(EtlJobName jobName, int jobRefId)
|
|
|
|
throws Exception {
|
|
|
|
Properties props;
|
|
|
|
try {
|
|
|
|
props = EtlJobPropertyDao.getJobProperties(jobName, jobRefId);
|
|
|
|
} catch (Exception e) {
|
|
|
|
Logger.error("Fail to update Kafka job properties for " + jobName.name() + ", ref id: " + jobRefId);
|
2016-08-03 18:55:07 -07:00
|
|
|
return;
|
|
|
|
}
|
2016-08-04 13:07:19 -07:00
|
|
|
Logger.info("Get Kafka job properties for " + jobName.name() + ", job ref id: " + jobRefId);
|
2016-07-26 12:16:34 -07:00
|
|
|
|
2016-08-03 18:55:07 -07:00
|
|
|
String[] topics = ((String) props.remove("kafka.topics")).split("\\s*,\\s*");
|
|
|
|
String[] processors = ((String) props.remove("kafka.processors")).split("\\s*,\\s*");
|
|
|
|
String[] dbTables = ((String) props.remove("kafka.db.tables")).split("\\s*,\\s*");
|
2016-07-25 14:44:02 -07:00
|
|
|
|
|
|
|
_props.clear();
|
2016-07-26 12:16:34 -07:00
|
|
|
_props.putAll(props);
|
|
|
|
|
|
|
|
_topics.clear();
|
|
|
|
for (int i = 0; i < topics.length; i++) {
|
|
|
|
// use 1 Kafka worker to handle each topic
|
|
|
|
_topics.put(topics[i], new Topic(topics[i], 1, processors[i], dbTables[i]));
|
2016-07-25 14:44:02 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-04 13:07:19 -07:00
|
|
|
/**
|
|
|
|
* update processor class, method and db writer for each topic
|
|
|
|
*/
|
|
|
|
public void updateTopicProcessor() {
|
|
|
|
for (String topic : _topics.keySet()) {
|
|
|
|
try {
|
|
|
|
// get the processor class and method
|
|
|
|
final Class processorClass = Class.forName(_topics.get(topic).processor);
|
|
|
|
_topicProcessorClass.put(topic, processorClass.newInstance());
|
|
|
|
|
|
|
|
final Method method = processorClass.getDeclaredMethod("process", GenericData.Record.class, String.class);
|
|
|
|
_topicProcessorMethod.put(topic, method);
|
|
|
|
|
|
|
|
// get the database writer
|
|
|
|
final DatabaseWriter dw = new DatabaseWriter(JdbcUtil.wherehowsJdbcTemplate, _topics.get(topic).dbTable);
|
|
|
|
_topicDbWriter.put(topic, dw);
|
|
|
|
} catch (Exception e) {
|
|
|
|
Logger.error("Fail to create Processor for topic: " + topic, e);
|
|
|
|
_topicProcessorClass.remove(topic);
|
|
|
|
_topicProcessorMethod.remove(topic);
|
|
|
|
_topicDbWriter.remove(topic);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public Object getProcessorClass(String topic) {
|
|
|
|
return _topicProcessorClass.get(topic);
|
|
|
|
}
|
|
|
|
|
|
|
|
public Method getProcessorMethod(String topic) {
|
|
|
|
return _topicProcessorMethod.get(topic);
|
|
|
|
}
|
|
|
|
|
|
|
|
public DatabaseWriter getDbWriter(String topic) {
|
|
|
|
return _topicDbWriter.get(topic);
|
|
|
|
}
|
|
|
|
|
|
|
|
public Map<String, DatabaseWriter> getTopicDbWriters() {
|
|
|
|
return _topicDbWriter;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* close the Config
|
|
|
|
*/
|
|
|
|
public void close() {
|
|
|
|
if (_consumer != null) {
|
|
|
|
_consumer.shutdown();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-25 14:44:02 -07:00
|
|
|
/**
|
2016-07-26 12:16:34 -07:00
|
|
|
* get Kafka configuration
|
|
|
|
* @return
|
2016-07-25 14:44:02 -07:00
|
|
|
*/
|
2016-08-04 13:07:19 -07:00
|
|
|
public Properties getProperties() {
|
2016-07-25 14:44:02 -07:00
|
|
|
return _props;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2016-07-26 12:16:34 -07:00
|
|
|
* get Kafka topics
|
|
|
|
* @return
|
2016-07-25 14:44:02 -07:00
|
|
|
*/
|
2016-08-04 13:07:19 -07:00
|
|
|
public Map<String, Topic> getTopics() {
|
2016-07-25 14:44:02 -07:00
|
|
|
return _topics;
|
|
|
|
}
|
|
|
|
|
2016-08-04 13:07:19 -07:00
|
|
|
public ConsumerConnector getConsumer() {
|
|
|
|
return _consumer;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setConsumer(ConsumerConnector consumer) {
|
|
|
|
_consumer = consumer;
|
|
|
|
}
|
|
|
|
|
|
|
|
public SchemaRegistryClient getSchemaRegistryClient() {
|
|
|
|
return _schemaRegistryClient;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setSchemaRegistryClient(SchemaRegistryClient schemaRegistryClient) {
|
|
|
|
_schemaRegistryClient = schemaRegistryClient;
|
|
|
|
}
|
2016-07-25 14:44:02 -07:00
|
|
|
}
|