[Arquitetura do sistema] A arquitetura e o princípio do middleware de mensagens

A função do middleware de mensagens é ser portadora de recursos de simultaneidade assíncrona, além de garantir muitos recursos na arquitetura, alta disponibilidade, alta simultaneidade, escalabilidade, confiabilidade, integridade, garantia de pedidos, etc. Isso causou dores de cabeça a vários designers; existem algumas necessidades anormais, como consumo lento, não repetitivo etc. O custo de design que precisa ser gasto é bastante alto, portanto, não supersticione cegamente o código aberto Daniel, para muitos mecanismos, quase É necessário reconstruir; não é tão simples criar uma nuvem privada adequada para todas as empresas, fácil de usar e universal.

Se um sistema de pagamento processa bilhões de pedidos comerciais todos os dias, a capacidade de processamento do middleware de mensagens deve ser de pelo menos quase 10 bilhões, porque muitos sistemas dependem da capacidade de cluster do middleware e, para garantir que nenhum erro possa ser cometido, deixe Vamos analisar um pouco o middleware em alguns aspectos da arquitetura.

Alta disponibilidade (alta disponibilidade)

A alta disponibilidade é um tópico eterno.Esta é também uma medida de confiabilidade no mundo financeiro.Você deve saber que os arquitetos do setor financeiro encontrarão maneiras de evitar a perda de dados, mesmo que sejam dados, mas de fato essa coisa Em teoria, isso depende do caráter. . . Isso não é uma cintilação.

Para dar um exemplo, na arquitetura de dados da Internet, pelo menos três cópias de dados são chamadas de altas garantias, mas, de fato, o data center belga do Google perdeu permanentemente 0,00001% após ser atingido por um raio em 8,13, abaixo de 0,05 % Dos discos não foram reparados. O que quero dizer aqui é que é a hora certa e a situação é muito importante. Não há nada impossível sob condições extremas, haverá vulnerabilidades de arquitetura. Vamos dar uma olhada na prática geral de alta disponibilidade do mq:

A figura a seguir é a solução HA do activemq:

1233356-702eb3dea716f13b.png

O HA do Activemq é hospedado por meio do failover mestre / escravo, onde o comutador mestre-escravo pode ser alternado de várias maneiras:

1: Use um nfs ou outro dispositivo de disco compartilhado para executar um bloqueio compartilhado.Marque o estado do mestre ocupando o bloqueio de arquivo compartilhado.Quando m desliga, o escravo correspondente ocupará o bloqueio compartilhado e converterá em mestre

2: O gerenciamento do cluster pelo zookeeper é mais comum e não será descrito aqui

A figura a seguir é a solução HA do metaq

1233356-a908be28c6cd391e.png

Conforme mostrado na figura acima, o mesmo se aplica aos nós mestre e escravo que gerenciam os intermediários através do zk.

Obviamente, esse é apenas um dos mecanismos de failover, que só garante que a mensagem seja convertida em escravo quando o broker desligar, mas não pode garantir a perda da mensagem no meio do processo.

Quando a mensagem flui do broker, é provável que seja causada por um tempo de inatividade ou outra falha de hardware, o que pode causar a perda da mensagem.Neste momento, é necessário um meio de armazenamento relevante para garantir a mensagem.

Em seguida, tomamos como referência o mecanismo de armazenamento do kafka. Devemos saber que a dependência do middleware de mensagens no armazenamento não exige apenas velocidade rápida, mas também requer um custo muito baixo dos requisitos de IO. O Kafka projetou um conjunto de mecanismos de armazenamento para atender aos requisitos acima. Introduzir.

Primeiro, o tópico no kafka é dividido em várias partições em uma implantação distribuída.A partição é equivalente a uma carga na mensagem e depois é roteada por várias máquinas.Por exemplo: um tópico debit_account_msg será dividido em debit_account_msg_0, debit_account_msg_0, debit_account_msg_1 , debit_account_msg_2. . . Aguarde N partições, cada partição irá gerar um diretório local como / debit_account_msg / topic

O arquivo dentro será dividido em muitos segmentos, cada segmento definirá um tamanho, como um segmento de 500mb, um arquivo é dividido em duas partes, índice e log

    00000000000000000.index
    00000000000000000.log
    00000000000065535.index
    00000000000065535.log

O número representa o ponto inicial do índice do valor de msgId e a estrutura de dados correspondente é a seguinte:

1233356-972f90ede17eaaa8.png

1,0 representa a mensagem com msgId de 1 e 0 representa o deslocamento neste arquivo.Depois de ler este arquivo, localize o arquivo de log de segmento correspondente e leia as informações de msg correspondentes. Formatar o corpo da mensagem:

1233356-cbdd6229fc1c0ea4.png

Obviamente, a aplicação simples desse mecanismo é definitivamente incapaz de atender à alta IO simultânea, primeiro procure o binário do arquivo de segmento, depois encontre os dados correspondentes por deslocamento, depois leia o msgsize, depois leia o corpo do relatório, pelo menos 4 vezes o disco io, a sobrecarga é relativamente grande , Mas a leitura seqüencial usada ao puxar tem basicamente pouco efeito.

Além da consulta acima. De fato, antes de gravar no disco, eles são lidos e gravados no pagecache no sistema operacional e, em seguida, o disco rígido é liberado (estratégia LRU) por meio de threads assíncronos, mas esse risco é realmente muito grande, porque, uma vez que o sistema operacional fica inativo, causará A perda de dados, especialmente no caso de consumo lento e reserva de muitos dados, mas o metaq mais jovem de Kafka fez muitas alterações nessa peça, e o mecanismo de replicação desses arquivos de partição (usados ​​por Ali), portanto, neste nível As chances de perda de mensagens devido a raios na Internet serão relativamente pequenas.Claro, não descarta o que acontece quando o cabo óptico na sala de host é cavado.

Dito isso, parece ser mais perfeito e bonito, mas na verdade o custo de operação e manutenção parece ser muito grande. Como esses são arquivos, quando ocorre um problema, é bastante problemático manipulá-lo manualmente, e ele está em uma única máquina e requer custos de operação e manutenção relativamente grandes para executar algumas especificações de operação e manutenção e recursos de chamada de API.

Portanto, nesta área, podemos transformar e armazenar dados em alguns nosql, como o mongoDB, é claro, o mysql também é possível, mas os recursos io e o nosqldb não estão no mesmo nível, a menos que tenhamos um forte mecanismo de processamento de transações e recursos financeiros. Li é realmente bastante rigoroso sobre esse requisito. Como o uso do metaq por trás do Alipay, porque o middleware anterior tbnotify será muito passivo no caso de consumo lento, e o metaq terá uma enorme vantagem nessa área.Por que, ouça a decomposição posteriormente.

Alta simultaneidade

No começo, a maioria dos engenheiros que usavam o mq era usada para resolver o problema da 性能soma.De 异步化fato, pelo mesmo ponto, io调度não se consome tanto recursos.Nem mais demoras, vejamos alguns dos pontos de alta simultaneidade no mq. Aqui estão alguns fundos famosos de middleware:

Na época, o Activemq era uma solução especializada em nível empresarial, em conformidade com a especificação jms em jee. Na verdade, o desempenho ainda era bom.

O Rabbitmq é escrito em linguagem erlang, cumpre as especificações do protocolo AMQP e é mais multiplataforma.O modo de transferência de modo deve ser mais rico e distribuído em

rocketmq (a versão mais recente do metaq3.0 hoje, o kafka também é o antecessor do metaq, foi inicialmente vinculado no sistema de mensagens de log de código aberto), o metaq basicamente escreveu o princípio e o mecanismo do kafka em java, depois de muitas transformações, transações de suporte, A velocidade de desenvolvimento é muito rápida e há comunidades muito boas em Ali e na China para fazer essa manutenção.

Para comparação de desempenho, aqui estão alguns dados da Internet apenas para referência:

1233356-9db0160ceb800c69.png

Para ser sincero, nesses níveis de dados, a diferença não é muito ridícula, mas podemos analisar alguns pontos em comum, quais são as principais diferenças de desempenho?

Rocketmq é o sucessor do metaq. Exceto por melhorias em alguns novos recursos e mecanismos, os princípios de desempenho são semelhantes. Aqui estão alguns destaques desses altos desempenhos:

O consumo do rocketmq usa principalmente o mecanismo pull, portanto, para o intermediário, muitos recursos de consumo não precisam ser implementados no broker, precisam apenas puxar os dados relevantes pelo consumidor e, como o activemq, o rabbitmq é mais antigo A maneira de permitir que os corretores despachem mensagens, é claro, esses também são alguns métodos de entrega padrão de jms ou amqp

O armazenamento de arquivos é armazenado sequencialmente, portanto, você só precisa chamar os dados do segmento quando recebe a mensagem, e o consumidor consome as informações ao máximo ao fazer o consumo, é improvável que produza uma lista de pendências e é possível definir io Os algoritmos de agendamento, como o modo noop, podem melhorar o desempenho de algumas leituras seqüenciais.

Através pagecachede acertar os dados cache do sistema operacional atinge um consumo de calor.

O IO do disco em lote e o IO da rede do metaq tentam executar os dados em um io, e as mensagens são todas em lotes, para que o planejamento do io não precise consumir muitos recursos.

A transmissão da NIO, como mostrado abaixo, é uma arquitetura do metaq original. O metaq original usou algumas estruturas NIO de alto desempenho integradas à lagartixa interna do Taobao e à notificação remota para distribuir mensagens:

1233356-fbc7dcdd0ded3c5d.png

A leveza da fila do consumidor, precisamos saber que nossos recursos de mensagens são obtidos através da fila

Veja a imagem abaixo:

1233356-dde4266c8cd62300.png

metaq adicionado fisicamente fila lógica fila de consumidor, a fila correspondente ao dos dados do disco é serializado, a fila não será adicionado para adicionar discos iowaitcarga, podem ser escritos sequencialmente, mas quando a leitura é ainda uma necessidade de ler o aleatório primeiro é a fila lógica, e, em seguida, ler o disco, por isso pagecacheé importante para tentar fazer um grande número de memória, essa alocação será totalmente utilizado.

De fato, o acima exposto pode basicamente garantir nosso desempenho em um nível relativamente alto; mas, às vezes, o desempenho não é o mais importante, o mais importante é fazer um equilíbrio ideal com outros recursos arquitetônicos; afinal, existem Outros mecanismos devem ser satisfeitos. Isso ocorre porque os três problemas mais difíceis do setor são: alta simultaneidade, alta disponibilidade e consistência.

Escalável

Essa é uma pergunta comum: para sistemas gerais ou middleware, ele pode ser melhor expandido, mas no middleware de mensagens, sempre foi um aborrecimento.

Deixe-me falar sobre as limitações da expansão do activemq primeiro, porque a expansão do activemq requer a natureza dos negócios. Como corretor, você deve primeiro conhecer a origem e o destino, mas se essas mensagens forem de transmissão distribuída, isso se tornará complicado. Vamos dar uma olhada no activemq. Como a carga é reproduzida:

1233356-b24977e544400a1d.png

Assumimos que o produtor envia mensagens do tópico A. Se todos os consumidores estiverem conectados a cada intermediário em circunstâncias normais, está quente? Se houver uma mensagem do produtor no intermediário, ele poderá ser transferido para o consumidor correspondente.

Mas se não houver um messager correspondente no broker2 na figura, o que devemos fazer neste caso? Como se supõe que existem muitos nós do sistema de aplicativos (produtor) e do sistema dependente (consumidor) do mesmo tópico, como expandir a capacidade? O Activemq pode fazer a parte normal da imagem acima, mas precisa alterar a configuração correspondente de produtor, corretor, consumidor, o que é bastante problemático.

Obviamente, o activemq também pode fazer pesquisa dinâmica por multicast (alguém mencionou que lvs ou f5 é usado como carga, mas há um grande problema para os consumidores, e essa configuração de carga não tem efeito substancial na distribuição de tópicos) No entanto, ainda haverá o problema que eu disse: se o tópico for muito grande, cada corretor precisará conectar todos os produtores ou consumidores, caso contrário, a situação que eu disse aparecerá e a expansão do activemq é bastante problemática a esse respeito.

Vamos falar sobre como o metaq faz isso, veja a imagem e fale:

1233356-888ca116dff81d84.png

O Metaq é particionado por tópico. Nesse nível, precisamos apenas configurar o máximo possível de partições de tópicos. Dessa forma, o fatiamento é ter um conceito de "negócios" como regra de roteamento; geralmente, existem muitas configurações em uma máquina intermediária. Tópico, cada tópico geralmente possui apenas uma partição em uma máquina; se a máquina não for suficiente, também poderá suportar várias partições; em geral, podemos usar o ID do negócio para modelar partições personalizadas, obtendo os parâmetros da área de envio É isso.

1233356-53305f2951166b6d.png
1233356-8b0c266b9ca55e6d.png

Confiabilidade

A confiabilidade é um recurso importante do middleware de mensagens.Vamos ver como o mq circula essas mensagens.Tome o activemq como uma referência primeiro.É baseado no mecanismo push & push.

Como garantir que todas as mensagens enviadas sejam consumidas? Os produtores da Activemq precisam receber uma confirmação do corretor após enviar uma mensagem para confirmar o recebimento.A mesma garantia também é fornecida para os corretores dos consumidores.

O mecanismo do Metaq também é o mesmo, mas o intermediário para o consumidor é puxado, portanto sua garantia de chegada depende da capacidade do consumidor, mas, em geral, é improvável que o cluster do servidor de aplicativos tenha um efeito de avalanche.

Como garantir a idempotência da mensagem? Atualmente, basicamente o activemq, o metaq não pode garantir a idempotência da mensagem, o que exige alguns negócios para garantir. Como o tempo limite do intermediário, ele será tentado novamente e, se tentado, novas mensagens serão geradas.É possível que o intermediário tenha chegado, portanto, nesse caso, não há garantia de que o mesmo pipeline de negócios produza duas mensagens.

Como garantir a confiabilidade da mensagem? Neste ponto, o activemq e o metaq basicamente têm o mesmo mecanismo:

Garantia do produtor: após a produção de dados para o corretor, é necessário persistir para retornar o ACK

Garantia do corretor: Após o servidor metaq receber a mensagem, ele é atualizado regularmente para o disco rígido e, em seguida, os dados são copiados para o escravo através de síncrono / assíncrono para garantir que o consumo não seja afetado após o tempo de inatividade.

O Activemq também é armazenado localmente através de um banco de dados ou arquivo para fazer a recuperação local

Garantia do consumidor: os consumidores de mensagens consomem mensagens um após o outro, e somente após o consumo bem-sucedido de uma mensagem eles continuarão consumindo a próxima. Se ele falhar ao consumir uma mensagem (como uma exceção), tentará consumi-la novamente (o máximo é 5 vezes por padrão). Após exceder o número máximo de vezes, ele ainda não poderá ser consumido e a mensagem será armazenada no disco local do consumidor, que é o encadeamento em segundo plano. Continue tentando novamente. O encadeamento principal continua a retroceder, consumindo mensagens subseqüentes. Portanto, somente após o MessageListener confirmar o consumo bem-sucedido de uma mensagem, o meta consumidor continuará consumindo outra mensagem. Isso garante o consumo confiável de mensagens.

Consistência

A consistência do mq discutimos dois cenários:

1: Garantir que a mensagem não será enviada / consumida várias vezes
2: Transação de garantia

Alguns dos mqs introduzidos acima não podem garantir consistência; então, por que não? O custo é relativamente alto, só se pode dizer que isso pode ser garantido modificando o código-fonte, e o esquema é relativamente não muito complicado, mas a sobrecarga adicional é relativamente grande, como por meio de um cluster de cache adicional para garantir um determinado período de tempo. Repetibilidade, acredito que deve haver algum mq com essa função.

O Activemq suporta dois tipos de transações, uma é a transação JMS e a outra é uma transação distribuída XA. Se você trouxer uma transação, um transactionId será gerado durante a interação com o intermediário. O intermediário implementa alguma TM para alocar o processamento da transação. XA, siga o padrão JTA. As garantias de transação activemq e metaq são todas feitas pelo método redo log, que é basicamente o mesmo.

A transação distribuída aqui é garantida apenas após o estágio do intermediário. Antes que o intermediário seja confirmado, a mensagem de preparação será armazenada no arquivo local e a mensagem será gravada na fila até o estágio de confirmação.Finalmente, o segundo estágio de confirmação é implementado por meio do TM.


Comunidade de desenvolvedores Kotlin

1233356-4cc10b922a41aa80

A conta pública da primeira comunidade de desenvolvedores Kotlin na China, principalmente compartilhando e trocando a linguagem de programação Kotlin, Spring Boot, Android, React.js / Node.js, programação funcional, idéias de programação e outros tópicos relacionados

Quanto mais barulhento o mundo, mais pensamento pacífico é necessário.

1665 artigos originais publicados · 1067 elogiados · 750.000 visualizações

Acho que você gosta

Origin blog.csdn.net/universsky2015/article/details/105531346
Recomendado
Clasificación