Отправка большого CSV в Kafka с помощью python Spark

Я пытаюсь отправить большой CSV Кафке. Основная структура состоит в том, чтобы прочитать строку CSV и закрепить ее заголовком.

a = dict(zip(header, line.split(",")

это затем преобразуется в json с:

message = json.dumps(a)

затем я использую библиотеку kafka-python для отправки сообщения

from kafka import SimpleProducer, KafkaClient
kafka = KafkaClient("localhost:9092")
producer = SimpleProducer(kafka)
producer.send_messages("topic", message)

использование PYSPARK Я легко создал RDD сообщений из файла CSV

sc = SparkContext()
text = sc.textFile("file.csv")
header = text.first().split(',')
def remove_header(itr_index, itr):
    return iter(list(itr)[1:]) if itr_index == 0 else itr
noHeader = text.mapPartitionsWithIndex(remove_header)

messageRDD = noHeader.map(lambda x: json.dumps(dict(zip(header, x.split(","))

теперь я хочу отправить эти сообщения: я определяю функцию

def sendkafka(message):
  kafka = KafkaClient("localhost:9092")
  producer = SimpleProducer(kafka)
  return producer.send_messages('topic',message)

Затем Я создайте новый RDD для отправки сообщений

sentRDD = messageRDD.map(lambda x: kafkasend(x))

затем я вызываю sentRDD.count ()

который начинает сбивать и отправлять сообщения

к сожалению, это происходит очень медленно. Он отправляет 1000 сообщений в секунду. Это на кластере 10 узлов по 4 процессора каждый и 8 ГБ памяти.

для сравнения, создание сообщений занимает около 7 секунд на 10 миллионов строк csv. ~ 2 ГБ

Я думаю, проблема в том, что я создаю экземпляр продюсера Кафки внутри функция. Однако, если я этого не делаю, spark жалуется, что производитель не существует, хотя я попытался определить его глобально.

возможно, кто-то может пролить свет на то, как эта проблема может быть решена.

спасибо,

1 ответов


вы можете создать одного производителя на раздел и использовать либо mapPartitions или foreachPartition:

def sendkafka(messages):
    kafka = KafkaClient("localhost:9092")
    producer = SimpleProducer(kafka)
    for message in messages:
        yield producer.send_messages('topic', message)

sentRDD = messageRDD.mapPartitions(sendkafka)

если выше только не поможет, вы можете попытаться расширить его с помощью асинхронный продюсер.

В Spark 2.x также можно использовать источник данных Kafka. Вам придется включить spark-sql-kafka jar, соответствующая версия Spark и Scala (здесь 2.2.0 и 2.11 соответственно):

spark.jars.packages  org.apache.spark:spark-sql-kafka-0-10_2.11:2.2.0

преобразование данных в DataFrame (если это не DataFrame уже):

messageDF = spark.createDataFrame(messageRDD, "string")

и писать DataFrameWriter:

(messageDF.write
    .format("kafka")
    .option("topic", topic_name)
    .option("kafka.bootstrap.servers", bootstrap_servers)
    .save())