Domanda

Sto costruendo una pipeline di elaborazione con NServiceBus ma ho problemi con la configurazione dei distributori per rendere scalabile ogni passaggio del processo.Ecco alcune informazioni:

  • La pipeline avrà un processo principale che dice "OK, è ora di iniziare" per un WorkItem, che avvierà quindi un processo come un diagramma di flusso.
  • Ogni passaggio nel diagramma di flusso può essere costoso dal punto di vista computazionale, quindi desidero la possibilità di ridimensionare ogni passaggio.Questo mi dice che ogni passaggio necessita di un distributore.
  • Voglio essere in grado di collegare ulteriori attività agli eventi in un secondo momento.Questo mi dice che devo pubblicare i messaggi() al termine, non inviarli.
  • Potrebbe essere necessario ramificare un processo in base a una condizione.Questo mi dice che un processo deve essere in grado di pubblicare più di un tipo di messaggio.
  • Potrebbe essere necessario unire i fork di un processo.Immagino che dovrei usare Sagas per questo.

Spero che questi presupposti siano buoni altrimenti sono più nei guai di quanto pensassi.

Per semplicità, dimentichiamoci di biforcazioni o unioni e consideriamo una pipeline semplice, con il passaggio A seguito dal passaggio B e che termina con il passaggio C.Ogni passaggio ha il proprio distributore e può avere molti nodi che elaborano i messaggi.

  • I nodi di lavoro NodeA contengono un processore IHandleMessages e pubblicano EventA
  • I nodi di lavoro NodeB contengono un processore IHandleMessages e pubblicano l'evento B
  • I nodi di lavoro NodeC contengono un processore IHandleMessages e quindi la pipeline è completa.

Ecco le parti rilevanti dei file di configurazione, dove # denota il numero del lavoratore, (es.ci sono code di input NodoA.1 e NodoA.2):

NodeA:
<MsmqTransportConfig InputQueue="NodeA.#" ErrorQueue="error" NumberOfWorkerThreads="1" MaxRetries="5" />
<UnicastBusConfig DistributorControlAddress="NodeA.Distrib.Control" DistributorDataAddress="NodeA.Distrib.Data" >
    <MessageEndpointMappings>
    </MessageEndpointMappings>
</UnicastBusConfig>

NodeB:
<MsmqTransportConfig InputQueue="NodeB.#" ErrorQueue="error" NumberOfWorkerThreads="1" MaxRetries="5" />
<UnicastBusConfig DistributorControlAddress="NodeB.Distrib.Control" DistributorDataAddress="NodeB.Distrib.Data" >
    <MessageEndpointMappings>
        <add Messages="Messages.EventA, Messages" Endpoint="NodeA.Distrib.Data" />
    </MessageEndpointMappings>
</UnicastBusConfig>

NodeC:
<MsmqTransportConfig InputQueue="NodeC.#" ErrorQueue="error" NumberOfWorkerThreads="1" MaxRetries="5" />
<UnicastBusConfig DistributorControlAddress="NodeC.Distrib.Control" DistributorDataAddress="NodeC.Distrib.Data" >
    <MessageEndpointMappings>
        <add Messages="Messages.EventB, Messages" Endpoint="NodeB.Distrib.Data" />
    </MessageEndpointMappings>
</UnicastBusConfig>

Ed ecco le parti rilevanti delle configurazioni del distributore:

Distributor A:
<add key="DataInputQueue" value="NodeA.Distrib.Data"/>
<add key="ControlInputQueue" value="NodeA.Distrib.Control"/>
<add key="StorageQueue" value="NodeA.Distrib.Storage"/>

Distributor B:
<add key="DataInputQueue" value="NodeB.Distrib.Data"/>
<add key="ControlInputQueue" value="NodeB.Distrib.Control"/>
<add key="StorageQueue" value="NodeB.Distrib.Storage"/>

Distributor C:
<add key="DataInputQueue" value="NodeC.Distrib.Data"/>
<add key="ControlInputQueue" value="NodeC.Distrib.Control"/>
<add key="StorageQueue" value="NodeC.Distrib.Storage"/>

Sto testando utilizzando 2 istanze di ciascun nodo e il problema sembra presentarsi a metà del nodo B.Fondamentalmente le cose che potrebbero succedere sono 2:

  1. Entrambe le istanze del Nodo B segnalano che si sta iscrivendo a EventA e anche che NodeC.Distrib.Data@MYCOMPUTER si sta iscrivendo a EventB pubblicato dal Nodo B.In questo caso funziona tutto alla grande.
  2. Entrambe le istanze del Nodo B segnalano che si sta iscrivendo a EventA, tuttavia, un lavoratore afferma che NodeC.Distrib.Data@MYCOMPUTER si sta abbonando DUE VOLTE, mentre l'altro lavoratore non lo menziona.

Nel secondo caso, che sembra essere controllato solo dal modo in cui il distributore instrada i messaggi di sottoscrizione, se il nodo "overachiever" elabora un EventA, tutto va bene.Se il "underachiever" elabora EventA, la pubblicazione di EventB non ha abbonati e il flusso di lavoro termina.

Quindi, le mie domande:

  1. È possibile questo tipo di configurazione?
  2. La configurazione è corretta?È difficile trovare esempi di configurazione con i distributori che vadano oltre la semplice configurazione a un livello di editore/2 lavoratori.
  3. Avrebbe più senso avere un processo broker centrale che esegua tutte le operazioni di polizia stradale non ad alta intensità di calcolo e invii messaggi ai processi dietro i distributori solo quando l'attività è di lunga durata e deve essere bilanciata dal carico?
    • Quindi i nodi con carico bilanciato potrebbero semplicemente rispondere al broker centrale, il che sembra più semplice.
    • D'altra parte, ciò sembra in contrasto con la decentralizzazione che è la forza di NServiceBus.
    • E se questa è la risposta e l'evento completato del processo a lunga esecuzione è una risposta, come si mantiene la pubblicazione che consente la successiva estensibilità sugli eventi pubblicati?
È stato utile?

Soluzione

Il problema che hai è che i tuoi nodi non vedono l'elenco degli abbonati degli altri.Il motivo per cui riscontri questo problema è che stai provando uno scenario di produzione (scale-out) con il profilo NServiceBus predefinito (lite) che non supporta lo scale-out ma rende lo sviluppo di una singola macchina molto produttivo.

Per risolvere il problema, esegui l'host NServiceBus utilizzando il profilo di produzione come descritto in questa pagina:

http://docs.particular.net/nservicebus/hosting/nservicebus-host/profiles

Ciò consentirà a diversi nodi di condividere lo stesso elenco di abbonati.

A parte questo, la tua configurazione è corretta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top