È un uso inefficiente del pattern Subscriber (PubSub)?

1

Ho un oggetto Publisher che solleva un evento a intervalli regolari (si pensi a qualcosa come un tick dell'orologio). Ho quindi 100s (o 1000s) di oggetti subscriber (tutte le istanze di un singolo tipo o due) che possono devono aggiornare autonomamente in risposta all'evento. Ma la maggior parte delle volte l'evento non si applica a loro, quindi lo ignorano. Quindi il metodo di gestione degli eventi nel Sottoscrittore ha un aspetto simile al seguente:

    private void changeHandler(int id)
    {
        if (id == this.ID) // rarely true
            val++; 
    }

Sono preoccupato perché l'inefficienza di questo approccio sta iniziando a colpire le prestazioni. (Dozzine di eventi aumentati ogni secondo, con migliaia di abbonati, sta diventando non trascurabile.)

Ora, succede proprio che il Publisher, in questo caso, sappia a quali sottoscrittori si applica ogni particolare evento (che è come può passare il parametro id ), così ho potuto bypassare completamente la strategia Event e fare in modo che l'editore aggiorni ciascun abbonato "manualmente" (per così dire). Ma ciò renderebbe il sistema più strettamente accoppiato, cosa che stavo cercando di evitare.

Esiste un approccio più efficiente a questa strategia di progettazione rispetto a quello che sto attualmente utilizzando? O un modello migliore del tutto che manterrebbe la separazione delle preoccupazioni tra l'editore e gli abbonati?

    
posta kmote 08.09.2017 - 00:31
fonte

3 risposte

2

La soluzione più semplice sarebbe quella di modificare la funzione subscribe per prendere l'id come argomento e aggiungere l'abbonato a una tabella hash con l'id come chiave. Quindi la funzione publish cercherebbe l'id nella tabella hash per ottenere tutti gli abbonati con quell'id e pubblicare solo su tali utenti.

Avresti un sovraccarico sopra le chiamate dirette, ma le ricerche con hashtable sono O(1) , quindi sarebbe sicuramente un miglioramento enorme rispetto all'esecuzione di un'istruzione if su ogni potenziale sottoscrittore.

    
risposta data 08.09.2017 - 02:33
fonte
1

Fondamentalmente, puoi decidere se i sottoscrittori devono essere eseguiti, lasciando loro vedere ogni pubblicazione. Oppure puoi far sì che l'editore "sappia" in qualche modo quali sono gli abbonati interessati a quali eventi, creando un accoppiamento più stretto di quello che vorremmo.

Oppure puoi delegare questa responsabilità a una nuova terza parte, che potrebbe consentire il disaccoppiamento che stai cercando.

C'è un algoritmo logico, chiamato RETE Algorithm . Questo algoritmo funziona con le regole del modulo: on condizione fai azione . Le condizioni possono essere espressioni complesse.

L'algoritmo cerca di ottimizzare il test delle condizioni per ogni regola in risposta agli eventi, nei casi in cui potrebbero esserci migliaia e migliaia di regole. Quello che fa l'algoritmo RETE è come il rilevamento e l'eliminazione di sottoespressione comuni nella tecnologia del compilatore. Trova sottoespressioni comuni nella parte delle condizioni delle varie regole e crea una struttura di regole interne e alternative che rappresenta le condizioni secondarie comuni tra tutte le regole ciascuna una sola volta. Mantiene una struttura dati tale che le regole attuali possano essere aggiunte / rimosse / modificate dinamicamente. Permette condizioni di eventi complessi (vale a dire una serie di eventi): nella sua struttura interna delle condizioni delle regole, ricorda quali sono le sub espressioni già attivate (già corrispondenti agli eventi precedenti). Quindi, dal momento che ha precalcolato sia le sottoespressioni che alcune condizioni precedenti, quando si verifica un evento, non deve fare molto lavoro per far avanzare lo stato della struttura interna e, infine, lanciare le azioni di una regola.

Esiste un parallelo qui, in cui gli abbonati hanno una condizione sulla quale possono agire, e possono esserci molti, molti abbonati e tutti osservano attributi simili; inoltre, gli abbonati possono cambiare le loro condizioni in modo dinamico.

Oltre a ciò, non c'è nulla che impedisca agli abbonati di continuare a testare le proprie condizioni e di non fare nulla se non c'è una corrispondenza adeguata. Ciò significa che in alcuni casi è possibile semplificare il linguaggio di espressione della terza parte, quindi esiste un potenziale per bilanciare la complessità di terze parti rispetto all'inefficienza della notifica ai sottoscrittori che non farebbero comunque nulla.

    
risposta data 08.09.2017 - 01:40
fonte
1

Il tuo editore è già strettamente associato a ciascun iscritto, poiché conosce le identità dei sottoscrittori e si aspetta che siano attivi e in esecuzione. Come osservano sia voi che Karl Bielefeldt, avere un N canali Pubub distinti per N abbonati avrebbe senso. In apache kafka puoi usare l'ID direttamente come nome del canale.

Se stai cercando resilienza e disaccoppiamento, potresti usare i canali 0.5 * N e richiedere al destinatario di confermare con un ACK sul canale. In questo modo il suo amico avrebbe notato la mancanza di ACK e potrebbe assumersi la responsabilità. Questo è un gruppo di amici K = 2, ma anche K più grandi funzionerebbe.

Il tuo esempio di incremento di un contatore locale è stato molto semplice, forse a scopo illustrativo. Gli eventi di incremento del contatore possono essere facilmente raggruppati. Se la coerenza del momento non è fondamentale per la tua applicazione, il publisher potrebbe voler aggregare alcuni di questi messaggi per ridurre il traffico dei messaggi.

    
risposta data 25.11.2017 - 19:01
fonte

Leggi altre domande sui tag