Práticas recomendadas para o Heartbeat em sistemas distribuídos

5

Tivemos em nosso sistema no passado um provedor de dados externo (chame-o de origem) enviando pulsações regulares para um aplicativo java (chame-o de cliente). Se a pulsação falhar, o sistema se desligará (para evitar a exibição de dados obsoletos em um aplicativo crítico). Isso foi direto, já que os dados e o heartbeat usavam o mesmo canal, tornando-o altamente confiável.

Desde então, passamos para um sistema distribuído com o cliente java dividido em vários microservices e dados que fluem em parte por meio de filas kafka entre serviços.

O mais importante - o sistema mais a montante (chamado de destino) ainda deve ter um batimento cardíaco confiável.

Se continuarmos enviando a pulsação por meio de um canal separado, qualquer falha em um dos microservices ou na fila kafka interromperá o fluxo de dados para o destino; por outro lado, a pulsação continuará fluindo sem interrupção. todo propósito de ter um batimento cardíaco

Uma solução que estou pensando é empurrar heartbeats através de todos os serviços e filas kafka para que eles tomem o mesmo caminho que os dados em si. Em qualquer caso, quais são os melhores padrões / critérios de projeto para reimplementação de pulsação em tal sistema distribuído?

    
por senseiwu 06.04.2018 / 12:00
fonte

3 respostas

4

Sua solução é óbvia. Quando cada serviço recebe uma pulsação de um de seus fontes, observe a origem e a hora e, quando esse serviço envia uma pulsação (para seus coletores), ele verifica se todas as fontes estão ativas.

Se você tiver fontes opcionais, "minhas fontes estão ativas" se torna mais complicado, mas você presumivelmente lidou com isso em como ele lida com dados, a pulsação precisa corresponder a essa abordagem.

Se ServiceA puder enviar dados para qualquer uma das três instâncias de ServiceB , ele deverá enviar as pulsações para todas as três instâncias .

Se ServiceC receber dados de qualquer uma das três instâncias de ServiceD , ele viu uma pulsação recente de sua D origem, se qualquer ServiceD enviou uma

    
por 06.04.2018 / 12:10
fonte
1

OK, então. Pelo que entendi você tem isso:

DataSource - pushes occasional messages to Clients

Client - Listens for datasource messages

Problema: Como o DataSource envia mensagens intermitentemente, se ele morrer, os clientes não serão informados e continuarão exibindo os dados antigos e agora inválidos.

Solução antiga:

DataSource - pushes occasional messages to Clients, 
    PLUS a regular small 'heartbeat' message

Client - Listens for DataSource messages and the 'heartbeat'. 
    If the heartbeat isn't received X seconds after the last one, 
    we know the DataSource has died and can take action.

Nova situação:

DataSource - pushes occasional messages to intermediate clients,

Load Balanced MicroService(1) - listens for datasource mesages 
    and pushes messages to next in chain

Load Balanced MicroService(n) - listens for MicroService(n-1) 
    and pushes messages to next in chain

Client - Listens for MicroService(last) messages, but the
    heartbeat is lost in the ether

Solução:

Os MicroServices devem se comportar como o cliente antigo e relatar quando sua fonte de dados falhou em seus ouvintes.

Mas enquanto as mensagens serão processadas por um único microsserviço em um grupo com balanceamento de carga, o batimento cardíaco deve ser processado por todos eles. Portanto, a pulsação deve usar o roteamento de fanout enquanto a mensagem deve usar uma fila de trabalho .

No entanto, é difícil continuar esse padrão ao longo da cadeia, pois cada processo de trabalho publica sua própria pulsação.

Eu sugeriria uma forma mais avançada de roteamento em que você tem um serviço de roteamento que esconde os trabalhadores do resto do mundo

Aqui, o trabalhador do seu roteador escuta as filas de entrada e distribui as tarefas para um grupo de trabalhadores. Ele recebe o trabalho concluído e o passa adiante. Escondendo os trabalhadores individuais. Ele pode lidar com trabalhadores que morrem ou demoram muito para completar o trabalho, incendiar novos trabalhadores quando estão sob carga, etc.

No seu caso, ele também pode lidar com o batimento cardíaco. garantir que o batimento cardíaco a jusante seja representativo das mensagens que está enviando.

    
por 06.04.2018 / 16:33
fonte
0

Um "heartbeat" é a solução do problema errado.

O consumidor dos microsserviços precisa se proteger contra o fornecimento de dados obsoletos quando qualquer um dos microsserviços cair.

Na verdade, uma pulsação, mesmo em sua configuração atual, não está realmente resolvendo o problema.

Se o banco de dados ficar inativo, um "heartbeat" que não se conecta ao banco de dados relatará que o aplicativo ainda está ativo. Eu corri para isso há vários anos. Pior ainda, você não pode presumir que cada micro serviço se conecta ao mesmo banco de dados.

Cada chamada individual para um micro serviço requer tratamento de erros para qualquer problema catastrófico que possa ocorrer desde o ponto de fazer a chamada (fonte) a todos os recursos usados pelo micro serviço. Você não pode obviamente dizer se o banco de dados de um micro serviço está desativado quando você precisa chamá-lo, mas algum tipo de resposta de erro HTTP retornará (4xx ou 5xx). E quando as respostas não retornam, os aplicativos que consomem os micro serviços precisam de tempo limite sensato em torno das chamadas.

Essa última peça do quebra-cabeça é um bom monitoramento do servidor de todo o ecossistema de tecnologia, e um meio bem definido e eficiente de informar as pessoas responsáveis por manter os consumidores de micro serviços de qualquer problema.

Bem-vindo à arquitetura de serviços orientados / micro serviços. As coisas funcionam muito bem quando funcionam, mas quando o caos reina, derrama.

    
por 06.04.2018 / 18:15
fonte