Detta dokument har översatts av AI. För eventuella felaktigheter, se den engelska versionen
I en enskild nodmiljö kan plugin vanligtvis uppfylla krav genom att använda tillstånd, händelser eller uppgifter inom processen. I ett klusterläge kan dock samma plugin köras på flera instanser samtidigt, vilket leder till följande typiska problem:
NocoBase-kärnan tillhandahåller olika middleware-gränssnitt på applikationsnivå för att hjälpa plugin att återanvända enhetliga funktioner i en klustermiljö. Följande avsnitt kommer att introducera användningen och bästa praxis för cachning, synkrona meddelanden, meddelandeköer och distribuerade lås, med referenser till källkod.
För data som behöver lagras i minnet rekommenderas det att använda systemets inbyggda cache-komponent för hantering.
app.cache.Cache tillhandahåller grundläggande operationer som set/get/del/reset och stöder även wrap och wrapWithCondition för att kapsla in cache-logik, samt batch-metoder som mset/mget/mdel.ttl för att förhindra cacheförlust vid omstart av instansen.Exempel: Cache-initialisering och användning i plugin-auth
Om tillståndet i minnet inte kan hanteras med en distribuerad cache (t.ex. om det inte kan serialiseras), behöver ändringen, när tillståndet ändras på grund av användaråtgärder, sändas till andra instanser via en synkron signal för att upprätthålla tillståndskonsistens.
sendSyncMessage, som internt anropar app.syncMessageManager.publish och automatiskt lägger till ett prefix på applikationsnivå till kanalen för att undvika konflikter.publish kan specificera en transaction, och meddelandet skickas efter att databastransaktionen har bekräftats, vilket säkerställer synkronisering av tillstånd och meddelande.handleSyncMessage för att bearbeta meddelanden från andra instanser. Att prenumerera under beforeLoad-fasen är mycket lämpligt för scenarier som konfigurationsändringar och schemasynkronisering.Meddelandesändning är den underliggande komponenten för synkrona signaler och kan även användas direkt. När ni behöver sända meddelanden mellan instanser kan ni använda denna komponent.
app.pubSubManager.subscribe(channel, handler, { debounce }) kan användas för att prenumerera på en kanal över instanser; debounce-alternativet används för att förhindra frekventa återanrop orsakade av upprepade sändningar.publish stöder skipSelf (standard är true) och onlySelf för att kontrollera om meddelandet ska skickas tillbaka till den aktuella instansen.Exempel: plugin-async-task-manager använder PubSub för att sända händelser för uppgiftsavbrott
Meddelandekön används för att schemalägga asynkrona uppgifter, lämplig för att hantera långvariga eller återförsöksbara operationer.
app.eventQueue.subscribe(channel, { idle, process, concurrency }). process returnerar en Promise, och ni kan använda AbortSignal.timeout för att kontrollera tidsgränser.publish lägger automatiskt till applikationsnamnsprefixet och stöder alternativ som timeout och maxRetries. Den använder som standard en minnesintern köadapter men kan vid behov växlas till utökade adaptrar som RabbitMQ.Exempel: plugin-async-task-manager använder EventQueue för att schemalägga uppgifter
När ni behöver undvika race conditions (konkurrensförhållanden) kan ni använda ett distribuerat lås för att serialisera åtkomst till en resurs.
local-adapter. Ni kan registrera distribuerade implementeringar som Redis. Använd app.lockManager.runExclusive(key, fn, ttl) eller acquire/tryAcquire för att kontrollera samtidighet.ttl används som en säkerhetsåtgärd för att släppa låset, vilket förhindrar att det hålls på obestämd tid i undantagsfall.Exempel: plugin-data-source-main använder ett distribuerat lås för att skydda borttagningsprocessen för fält
app.cache och app.syncMessageManager för att undvika att återimplementera logik för kommunikation mellan noder i plugin.transaction.afterCommit (syncMessageManager.publish har detta inbyggt) för att säkerställa data- och meddelandekonsistens.timeout, maxRetries och debounce-värden för att förhindra nya trafiktoppar i exceptionella situationer.Med dessa funktioner kan plugin säkert dela tillstånd, synkronisera konfigurationer och schemalägga uppgifter över olika instanser, vilket uppfyller kraven på stabilitet och konsistens i klusterdistributionsscenarier.