Técnicas reais: faísca fluxo de dados cenário de aplicação ler modo -Kafka

página blog pessoal de navegação (clique à direita ligação para abrir um blog pessoal): Daniel levá-lo em tecnologia de pilha 

esboço

Faísca suporte para streaming em tempo real para a leitura de vários dados de origem de entrada, incluindo Kafka, canal, fluxo de soquete e similares. Além de fonte de entrada em tempo real diferente de Kafka, por causa de nosso cenário de negócios não está envolvido, isso não será discutido. Este artigo é focada principalmente em nosso cenário de negócios atual, faísca única causa Transmissão ler dados Kafka. Faísca streaming ofertas oficiais duas maneiras de ler os dados Kafka:

  • Abordagem primeiro receptor-based. Este tipo de apoio do primeiro modo oficial de leitura, e fornece a perda de dados zero (perda de dados zero) no suporte de faísca 1,2;
  • Primeira Abordagem Direta (Sem Receivers). Este tipo de modo de leitura incorporados faísca 1.3.

A presença destas duas maneiras muito diferentes de ler, é claro, vantagens e desvantagens. Em seguida, vamos dissecar modo esses dois dados específicos ler.

一, Abordagem baseada-Receptor

Como descrito anteriormente, de faísca Kafka oficial primeiro para fornecer dados com base nos padrões de consumo receptor. Mas haverá um programa pode falhar perda de dados, após a introdução de um parâmetro de configuração em 1,2 faísca spark.streaming.receiver.writeAheadLog.enablepara evitar este risco. O seguinte é as palavras do funcionário:

na configuração padrão, essa abordagem pode perder dados sob falhas (ver confiabilidade receptor. Para garantir a perda de dados zero, você tem que permitir adicionalmente Logs Write Ahead em faísca streaming (introduzido em faísca 1.2). Esta forma síncrona salva todos os dados Kafka recebidos em logs de gravação à frente em um sistema de arquivos distribuídos (por exemplo HDFS), de modo que todos os dados podem ser recuperados em caso de falha.

modo de leitura à base de receptor

forma-base do receptor de leitura api Kafka Kafka de ordem superior (de alto nível) para obtenção de dados de consumo baseados na Kafka. Depois de submeter faísca streaming tarefa, conjunto de faísca será reservado para especificamente designados receptores e contínua, de leitura de dados assíncrona Kafka ler intervalos de tempo e os deslocamentos de cada alcance de leitura pode ser configurado por meio de parâmetros. Receptor armazenado nos dados de leitura, o específico StorageLevelmodo especificado pelo utilizador, tal como MEMORY_ONLYe similares. Quando as tarefas de lote gatilho motorista nos receptores de dados serão transferidos para o resto dos Executores de execução. Depois de realizar, receptores será actualizado em conformidade offsets ZooKeeper de. Se você quiser ter certeza de que pelo menos uma vez no modo de leitura pode ser definido spark.streaming.receiver.writeAheadLog.enablecomo verdadeiro. processo de aplicação específico receptor mostrado abaixo:

Digite Caption

Receptor com base leitura alcançado

dados de alto nível de Kafka leu modo permite que os usuários se concentrem nos dados de leitura, sem a atenção ou manutenção deslocamentos do consumidor, o que reduz a quantidade de código e carga de trabalho do usuário e relativamente simples. Assim, no início da introdução da faísca mecanismo de cálculo streaming, usamos essa maneira de dar prioridade aos dados de leitura, o código específico é a seguinte:

 /*读取kafka数据函数*/
  def getKafkaInputStream(zookeeper: String,
                            topic: String,
                            groupId: String,
                            numRecivers: Int,
                            partition: Int,
                            ssc: StreamingContext): DStream[String] = {
    val kafkaParams = Map(
      ("zookeeper.connect", zookeeper),
      ("auto.offset.reset", "largest"),
      ("zookeeper.connection.timeout.ms", "30000"),
      ("fetch.message.max.bytes", (1024 * 1024 * 50).toString),
      ("group.id", groupId)
    )
    val topics = Map(topic -> partition / numRecivers)

    val kafkaDstreams = (1 to numRecivers).map { _ =>
      KafkaUtils.createStream[String, String, StringDecoder, StringDecoder](ssc,
        kafkaParams,
        topics,
        StorageLevel.MEMORY_AND_DISK_SER).map(_._2)
    }

    ssc.union(kafkaDstreams)
  }

Como o código acima, a função getKafkaInputStreamfornecida zookeepertopicgroupIdnumReceiverspartitione ssc, os quais são passados para a função correspondente a:

  • zookeeper: informações de conexão ZooKeeper
  • tópico: informações tópico Kafka entrou
  • groupId: informação do consumidor
  • numReceivers: o número de receptor pretendido, em e utilizada para ajustar a simultaneidade
  • partição: Kafka correspondente ao número de partições tópico

Os principais parâmetros utilizados para conectar mais do que alguns Kafka Kafka e ler dados. passos específicos realizados são os seguintes:

  • Kafka ler os parâmetros relacionados, em que  zookeeper.connectisto passando zookeeper parâmetros de entrada; auto.offset.resetdefinir o início do último os dados são lidos a partir do tema; zookeeper.connection.timeout.msrefere-se zookeepr período de tempo limite de ligação para evitar a instabilidade rede; fetch.message.max.bytesrefere-se a um único dados lidos tamanho; group.idele é designado um consumidor.
  • Especifica o número de tópico concorrente, quando o número especificado de receptores, mas desde que o número de receptores é menor do que o número de tópico de partição, então cada receptor vai jogar acima da rosca correspondente ao ler uma partição diferente.
  • Kafka ler dados, numReceivers parâmetros para isso, precisamos especificar quantas Executor como receptores, receptores são mais abertos, a fim de melhorar o rendimento do aplicativo.
  • Dados leia união para associar uma pluralidade de Receiver

questões de leitura à base de receptor

Usando formas baseadas em Reveiver para atender às necessidades de algumas das nossas cenas, e com base nisso alguns resumo do micro-lote, em memória modelo de computação. Em cenários específicos, temos que esta forma de fazer alguma otimização:

  • prevenção de perda de dados. Fazer operações de ponto de verificação e configuração spark.streaming.receiver.writeAheadLog.enableparâmetros;
  • Melhorar a taxa de transferência de dados receptor. Usando MEMORY_AND_DISK_SERleituras de dados, melhora a memória de receptor único ou transferir grande grau de paralelismo, distribuído para a pluralidade de dados para o receptor.

A abordagem acima, até certo ponto, para atender nossos cenários de aplicação, tais como micro-lotes e em memória modelo de computação. Mas, ao mesmo tempo, porque esses dois fatores, bem como outros aspectos do problema vai levar a uma variedade de situações:

  • Configuração spark.streaming.receiver.writeAheadLog.enableparâmetros, o processamento seja feito antes de cada lote com o ponto de verificação no directório de registo, o que reduz a eficiência de processamento de dados, por sua vez, aumentou a fim Receptor pressão; Além disso uma vez que o mecanismo de apoio de dados, a carga vai ser afectada, uma carga elevada o risco de atraso ocorre, resultando em falhas de aplicação.
  • Usando MEMORY_AND_DISK_SERos requisitos de memória reduzidos. Mas o cálculo velocidade de impacto, em certa medida,
  • memória do receptor único. Desde o receptor é parte do Executor, em seguida, a fim de aumentar a produtividade, melhora da memória do receptor. Mas em cada computação lote, lote envolvidos no cálculo e não vai usar tanta memória, resultando em um grave desperdício de recursos.
  • Grau de paralelismo utilizado para armazenar uma pluralidade de dados Receptor Kafka. Receptor ler dados é assíncrona e não participa no cálculo. Se o grau de paralelismo abertura para equilibrar a alta taxa de transferência não vale a pena.
  • Asynchronous Receiver Executor e calculados, em seguida, os fatores causais encontradas na rede, levando a atrasos na computação, fila de computação tem vindo a aumentar, enquanto o receptor tem sido para os dados de recepção, é muito fácil de fazer com que o programa deixe de funcionar.
  • Quando o programa não conseguir recuperar, pode haver porção de dados do chão, mas o programa falhar, o caso das compensações não é atualizado, o que leva a uma duplicação do consumo de dados.

Para retornar à prestação dos problemas acima, reduzir o uso de recursos, que mais tarde adotou aproximação direta Kafka para ler os dados, especificamente a próxima elaborados.

二, Abordagem Direta (Sem Receivers)

Diferente dos métodos baseados no receptor de consumo de dados, faísca introdução oficial de modo directo Kafka consumo de dados em 1,3 faísca. Em relação à abordagem baseada no receptor, modo directo apresentar vantagens nas seguintes áreas:

  • Paralela simplificado (simplificado Paralelismo). Agora não precisa criar múltiplas fontes de entrada e sindicais, Kafka tema de partição ea partição RDD-one correspondência, o funcionário descreveu da seguinte forma:

Não há necessidade de criar de entrada múltipla Kafka córregos e união deles. Com directStream, faísca Transmissão irá criar quantas partições RDD como existem partições Kafka para consumir, o que todos os dados lidos a partir de Kafka em paralelo. Portanto, há um mapeamento um-para-um entre Kafka e RDD partições, o que é mais fácil de entender e ajustar.

  • Eficiência (eficiência). Receptor baseada em para garantir perda zero de dados (perda de dados zero) precisa ser configurado spark.streaming.receiver.writeAheadLog.enable, desta forma necessidade de salvar duas cópias de dados, desperdício de espaço de armazenamento também afeta a eficiência. O caminho direto este problema não existe.

Alcançar perda de dados zero na primeira abordagem exigia que os dados sejam armazenados em um Write Ahead Log, que ainda replicado os dados. Esta é realmente ineficiente como os dados de forma eficaz é replicado duas vezes - uma por Kafka, e uma segunda vez pela Write Ahead Log. Esta segunda abordagem elimina o problema porque não há nenhum receptor e, portanto, não há necessidade de Write Ahead Logs. Contanto que você tem retenção de Kafka suficiente, as mensagens podem ser recuperados a partir de Kafka.

  • Fortes consistentes semântica (semântica Precisamente-uma vez). dados de alto nível, mas deslocamentos são mantidos pela faísca Streaming de consumido por Zookeeper. Pelo parâmetro de configuração pode ser alcançado a-menos uma vez ao consumidor, esta situação pode repetir dados de consumo.

A primeira abordagem utiliza alta API nível de Kafka para armazenar deslocamentos consumidos no Zookeeper. Esta é tradicionalmente a maneira de consumir dados de Kafka. Embora essa abordagem (em combinação com os registros de escrita à frente) pode garantir a perda de dados zero (ou seja, pelo menos uma vez-semântica), há uma pequena chance de alguns registros podem ficar consumidos duas vezes sob algumas falhas. Isto ocorre devido a inconsistências entre os dados de forma confiável recebidas por faísca Transmissão e deslocamentos monitorados pela Zookeeper. Assim, nesta segunda abordagem, usamos simples API Kafka que não usa Zookeeper. Os deslocamentos são monitorados por faísca streaming dentro de seus postos de controle. Isso elimina inconsistências entre faísca Streaming e Zookeeper / Kafka, e assim cada registro é recebido por faísca streaming efetivamente exatamente uma vez, apesar de falhas. A fim de alcançar a semântica exatamente-uma vez para a saída de seus resultados,

modo de leitura direta

modo direto usa maneira simples api consumidor de Kafka para ler os dados, sem passar por ZooKeeper, desta forma não requerem mais especializada Receiver para ler continuamente os dados. Sempre que uma tarefa é disparada, os dados são lidos pelo Executor, e participe de outra Executor do processo de cálculo de dados para ir. leia o motorista decidir como muitos deslocamentos e offsets referidos postos de controle para manter. Irá desencadear a próxima tarefa batch, em seguida, ler Kafka e calculados dados pelo executor. A partir deste processo, podemos encontrar maneiras Receptor direto sem ter que ler os dados, mas necessidade de ler o cálculo de dados, de modo que o consumo de dados direto menos exigente modo de memória, e só precisa considerar o lote memória pode necessário computação; outro lote quando as tarefas se acumulam, isso não afetará o acúmulo de dados. FIG específico lê como se segue:

Digite Caption

realização leitura direta

Faísca Transmissão fornece uma série de dados sobrecarregados ler método de Kafka, este trabalho enfoca dois abordagem baseada em Scala, que será utilizado em nosso cenário de aplicação, o código método específico é a seguinte:

  • Um método createDirectStreamem sscum StreamingContext; kafkaParamsconfiguração específica ver a configuração do meio da base-Receiver, com o mesmo, há de notar que fromOffsets , que é usado para especificar o que começa a ler dados a partir do offset.
def createDirectStream[
    K: ClassTag,
    V: ClassTag,
    KD <: Decoder[K]: ClassTag,
    VD <: Decoder[V]: ClassTag,
    R: ClassTag] (
      ssc: StreamingContext,
      kafkaParams: Map[String, String],
      fromOffsets: Map[TopicAndPartition, Long],
      messageHandler: MessageAndMetadata[K, V] => R
  ): InputDStream[R] = {
    val cleanedHandler = ssc.sc.clean(messageHandler)
    new DirectKafkaInputDStream[K, V, KD, VD, R](
      ssc, kafkaParams, fromOffsets, cleanedHandler)
  }
  • método CreateDirectStream, o método requer apenas três parâmetros, que kafkaParamsainda é o mesmo, o que muda não são, mas que tem uma configuração auto.offset.resetpode ser usado para especificar iniciar a leitura de dados a partir da maior ou menor; topicrefere-se ao Tópico Kafka, você pode especificar mais. O método de código específicas são como se segue:
def createDirectStream[
    K: ClassTag,
    V: ClassTag,
    KD <: Decoder[K]: ClassTag,
    VD <: Decoder[V]: ClassTag] (
      ssc: StreamingContext,
      kafkaParams: Map[String, String],
      topics: Set[String]
  ): InputDStream[(K, V)] = {
    val messageHandler = (mmd: MessageAndMetadata[K, V]) => (mmd.key, mmd.message)
    val kc = new KafkaCluster(kafkaParams)
    val fromOffsets = getFromOffsets(kc, kafkaParams, topics)
    new DirectKafkaInputDStream[K, V, KD, VD, (K, V)](
      ssc, kafkaParams, fromOffsets, messageHandler)
  }

Em um cenário de aplicação prática, vamos usar a combinação dos dois métodos, uma direção dividido em dois aspectos:

  • arranque da aplicação. Quando o desenvolvimento do programa e em linha, ainda dados sobre o consumo Kafka, do maior para ler dados de, neste momento, o segundo método;
  • reinicialização do aplicativo. Quando o recurso por outras razões, a rede como resultado da incapacidade de reiniciar o programa, certifique-se de começar a ler dados dos deslocamentos anteriores neste momento, precisamos usar o primeiro método para garantir que a nossa cena.

direção geral, usamos o método acima para atender às nossas necessidades, é claro, as estratégias específicas que não são discutidos neste blog, haverá um artigo de acompanhamento especial para introduzir. códigos de dados Kafka lido a partir da maior ou menor alcançar o seguinte:

/**
    * 读取kafka数据,从最新的offset开始读
    *
    * @param ssc         : StreamingContext
    * @param kafkaParams : kafka参数
    * @param topics      : kafka topic
    * @return : 返回流数据
    */
private def getDirectStream(ssc: StreamingContext,
                            kafkaParams: Map[String, String],
                            topics: Set[String]): DStream[String] = {
  val kafkaDStreams = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder](
    ssc,
    kafkaParams,
    topics
  )
  kafkaDStreams.map(_._2)
}

Falha ao reiniciar código da lógica da seguinte forma:

/**
    * 如果已有offset,则从offset开始读数据
    *
    * @param ssc         : StreamingContext
    * @param kafkaParams : kafkaParams配置参数
    * @param fromOffsets : 已有的offsets
    * @return : 返回流数据
    */
private def getDirectStreamWithOffsets(ssc: StreamingContext,
                                       kafkaParams: Map[String, String],
                                       fromOffsets: Map[TopicAndPartition, Long]): DStream[String] = {
  val kfkData = try {
    KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder, String](
      ssc,
      kafkaParams,
      fromOffsets,
      (mmd: MessageAndMetadata[String, String]) => mmd.message()
    )
  } catch { //offsets失效, 从最新的offsets读。
    case _: Exception =>
    val topics = fromOffsets.map { case (tap, _) =>
      tap.topic
    }.toSet
    getDirectStream(ssc, kafkaParams, topics)
  }
  kfkData
}

Código fromOffsetsparâmetro adquiridos a partir de um armazenamento e processamento externo exigem código de conversão é a seguinte:

val fromOffsets = offsets.map { consumerInfo =>
  TopicAndPartition(consumerInfo.topic, consumerInfo.part) -> consumerInfo.until_offset
}.toMap

O método fornece Kafka lido de deslocamentos especificados dos dados. Se você encontrar um leitura de dados anormais, acreditamos que compensa uma falha, tal situação para pegar essa exceção, Kafka, em seguida, ler os dados do maior escritório.

problemas de leitura direta

Em aplicações práticas, Direct Approach uma boa maneira de satisfazer as nossas necessidades, em comparação com o modo baseado em Receiver, há vantagens nas seguintes áreas:

  • Reduzir recurso. Direta não precisa receptores e executores todos os seus aplicativos para participar das tarefas computacionais; baseada em receptor e é necessário para ler Kafka especiais Receptores não participam nos dados de cálculo. Portanto, aplicar os mesmos recursos, Direct ser capaz de suportar grandes empresas.

  • Reduzir a memória. -Receptor com base receptor em outro Exectuor é assíncrona, e continuou a receber dados para o pequeno volume de cenários de negócios Felizmente, se encontrou tráfego pesado, a necessidade de melhorar a memória do receptor, mas envolvido no cálculo do Executor e não precisam de tanta memória. E porque não há receptor direta, mas o cálculo dos dados lidos e cálculo direto, os baixos requisitos de memória. aplicações práticas, podemos colocar o original 10G é agora para cerca de 2-4G.

  • Mais robusto. método baseado receptor requer receptores para ler dados assíncronos contínuos, os fatores encontrados de rede, tais como a carga de armazenamento, resultando na acumulação de tempo real surgem tarefas, mas Receptores continua a ler os dados, esta situação pode facilmente levar ao colapso do cálculo. Dirigir sem tais preocupações, que quando acionado driver lote de computação tarefas, irá ler os dados e cálculos. acumulação fila ocorre não causa a falha do programa.

Quanto a outras vantagens, tais como paralelo simplificado (simplificado paralelismo), eficiência (Eficiência) e semântica altamente consistentes (Exactamente-uma vez semântica) listados antes e não será descrito. Embora direto tem essas vantagens, mas existem algumas deficiências, como segue:

  • Aumentar os custos. Direto requer que o usuário a adotar o ponto de verificação ou de armazenamento de terceiros para manter as compensações, ao invés da base-receptor a manter compensações por ZooKeeper, isso aumenta os custos de desenvolvimento do usuário.
  • Monitoramento visualização. tópico forma especificada com base em receptor de consumo do consumidor especificado pode ser monitorado por ZooKeeper, enquanto direto não é tão conveniente, se for feito o monitoramento e visualização, você precisa colocar o desenvolvimento humano.

aprendizagem anexado Java / C / C ++ / máquina / Algoritmos e Estruturas de Dados / front-end / Android / Python / programador de leitura / únicos livros livros Daquan:

(Clique no direito de abrir lá no blog pessoal seco): seca Técnico Floração
===== >> ① [Java Daniel levá-lo no caminho para a avançada] << ====
===== >> ② [+ acm algoritmo de estrutura de dados Daniel levá-lo no caminho para a avançada] << ===
===== >> ③ [banco de dados Daniel levá-lo no caminho para a avançada] << == ===
===== >> ④ [front-end Daniel web para levá-lo no caminho para a avançada] << ====
===== >> ⑤ [machine python aprendizagem e Daniel levá-lo entrada para o estrada avançada] << ====
===== >> ⑥ [arquiteto Daniel levá-lo no caminho para a avançada] << =====
===== >> ⑦ [C ++ Daniel avançou para levá-lo na estrada] << ====
===== >> ⑧ [ios Daniel levá-lo no caminho para a avançada] << ====
=====> > ⑨ [segurança web Daniel levá-lo no caminho para a avançada] << =====
===== >> ⑩ [sistema operacional Linux e Daniel levá-lo no caminho para a avançada] << = ====

Não há frutas não ganhos, espero que você jovens amigos, amigos querem aprender técnicas, superando todos os obstáculos no caminho da estrada determinado a amarrar em tecnologia, entender o livro, e em seguida, bater no código, entender o princípio, e ir prática, vai ele vai lhe trazer a vida, seu trabalho, seu futuro um sonho.

Publicado 47 artigos originais · ganhou elogios 0 · Visualizações 284

Acho que você gosta

Origin blog.csdn.net/weixin_41663412/article/details/104860416
Recomendado
Clasificación