Esta documentação foi traduzida automaticamente por IA.
Em um ambiente de nó único, os plugins geralmente conseguem atender aos requisitos usando estados, eventos ou tarefas dentro do próprio processo. No entanto, em um modo de cluster, o mesmo plugin pode estar rodando em várias instâncias ao mesmo tempo, o que traz os seguintes problemas comuns:
O núcleo do NocoBase oferece várias interfaces de middleware na camada de aplicação para ajudar os plugins a reutilizar capacidades unificadas em um ambiente de cluster. A seguir, vamos apresentar o uso e as melhores práticas de cache, mensagens síncronas, filas de mensagens e bloqueios distribuídos, com referências ao código-fonte.
Para dados que precisam ser armazenados em memória, recomendamos usar o componente de cache integrado do sistema para gerenciamento.
app.cache.Cache oferece operações básicas como set/get/del/reset, e também suporta wrap e wrapWithCondition para encapsular a lógica de cache, além de métodos em lote como mset/mget/mdel.ttl (time-to-live) razoável para evitar a perda de cache em caso de reinício da instância.Exemplo: Inicialização e uso de cache no plugin-auth
Se o estado em memória não puder ser gerenciado com um cache distribuído (por exemplo, se não puder ser serializado), então, quando o estado mudar devido a ações do usuário, essa mudança precisará ser notificada às outras instâncias por meio de um sinal síncrono para manter a consistência do estado.
sendSyncMessage, que internamente chama app.syncMessageManager.publish e adiciona automaticamente um prefixo de nível de aplicação ao canal para evitar conflitos.publish pode especificar uma transaction, e a mensagem será enviada somente após a confirmação da transação do banco de dados, garantindo a sincronização entre o estado e a mensagem.handleSyncMessage para processar mensagens de outras instâncias. A inscrição durante a fase beforeLoad é muito adequada para cenários como alterações de configuração e sincronização de esquema.A transmissão de mensagens é o componente subjacente dos sinais síncronos e também pode ser usada diretamente. Quando você precisar transmitir mensagens entre instâncias, pode usar este componente.
app.pubSubManager.subscribe(channel, handler, { debounce }) pode ser usado para assinar um canal entre instâncias; a opção debounce é usada para evitar chamadas de retorno frequentes causadas por transmissões repetidas.publish suporta skipSelf (padrão é true) e onlySelf para controlar se a mensagem é enviada de volta para a própria instância.Exemplo: plugin-async-task-manager usa PubSub para transmitir eventos de cancelamento de tarefas
A fila de mensagens é usada para agendar tarefas assíncronas, sendo ideal para operações de longa duração ou que podem ser retentadas.
app.eventQueue.subscribe(channel, { idle, process, concurrency }). O process retorna uma Promise, e você pode usar AbortSignal.timeout para controlar os tempos limite.publish adiciona automaticamente o prefixo do nome da aplicação e suporta opções como timeout e maxRetries. Por padrão, ele se adapta a uma fila em memória, mas pode ser alternado para adaptadores estendidos como RabbitMQ, conforme a necessidade.Exemplo: plugin-async-task-manager usa EventQueue para agendar tarefas
Quando você precisa evitar condições de corrida, pode usar um bloqueio distribuído para serializar o acesso a um recurso.
local baseado em processo. Você pode registrar implementações distribuídas como Redis; use app.lockManager.runExclusive(key, fn, ttl) ou acquire/tryAcquire para controlar a concorrência.ttl (time-to-live) é usado como uma salvaguarda para liberar o bloqueio, evitando que ele seja mantido indefinidamente em casos excepcionais.Exemplo: plugin-data-source-main usa um bloqueio distribuído para proteger o processo de exclusão de campos
app.cache e app.syncMessageManager para evitar reimplementar a lógica de comunicação entre nós nos plugins.transaction.afterCommit (já integrado no syncMessageManager.publish) para garantir a consistência dos dados e das mensagens.timeout, maxRetries e debounce para evitar novos picos de tráfego em situações excepcionais.Com essas capacidades, os plugins podem compartilhar estados com segurança, sincronizar configurações e agendar tarefas entre diferentes instâncias, atendendo aos requisitos de estabilidade e consistência em cenários de implantação em cluster.