Elaboriamo i messaggi attraverso una varietà di servizi (un messaggio toccherà probabilmente 9 servizi prima di essere eseguito, ciascuno con una specifica funzione relativa all'IO). In questo momento abbiamo una combinazione del caso peggiore (serializzazione del contratto dati XML) e del caso migliore (MSMQ in memoria) per le prestazioni.
La natura del messaggio significa che i nostri dati serializzati finiscono per circa 12-15 kilobyte e che elaboriamo circa 4 milioni di messaggi a settimana. I messaggi persistenti in MSMQ erano troppo lenti per noi e quando i dati crescono sentiamo la pressione dei file mappati in memoria di MSMQ. Il server ha 16 GB di memoria in uso e in crescita, solo per l'accodamento. Le prestazioni subiscono anche quando l'utilizzo della memoria è elevato, poiché la macchina inizia a scambiare. Stiamo già eseguendo il comportamento di autopulizia MSMQ.
Sento che c'è una parte che stiamo facendo di sbagliato qui. Ho provato a usare RavenDB per rendere persistenti i messaggi e ho semplicemente messo in coda un identificatore, ma le prestazioni erano molto lente (al massimo 1000 messaggi al minuto). Non sono sicuro che sia il risultato dell'utilizzo della versione di sviluppo o di cosa, ma abbiamo sicuramente bisogno di un throughput più elevato [1]. Il concetto ha funzionato molto bene in teoria, ma le prestazioni non erano all'altezza del compito.
Il modello di utilizzo ha un servizio che funge da router, che fa tutte le letture. Gli altri servizi collegheranno le informazioni in base al loro hook di terze parti e inoltreranno nuovamente al router. La maggior parte degli oggetti viene toccata 9-12 volte, anche se circa il 10% è costretto a circolare in questo sistema per un po 'fino a quando le terze parti rispondono in modo appropriato. I servizi ora tengono conto di questo e hanno comportamenti di sonno appropriati, poiché per questo motivo utilizziamo il campo prioritario del messaggio.
Quindi, la mia domanda, qual è lo stack ideale per il passaggio di messaggi tra macchine discrete ma LAN in un ambiente C # / Windows? Normalmente inizierei con BinaryFormatter invece della serializzazione XML, ma è un buco nel coniglio se un modo migliore è scaricare la serializzazione in un archivio documenti. Quindi, la mia domanda.
[1]: la natura della nostra attività significa che prima elaboriamo i messaggi, più soldi facciamo. Abbiamo empiricamente dimostrato che l'elaborazione di un messaggio più avanti nella settimana significa che abbiamo meno probabilità di fare quei soldi. Mentre le prestazioni di "1000 al minuto" sembrano molto veloci, abbiamo davvero bisogno di quel numero fino a 10k / minuto. Solo perché sto fornendo numeri nei messaggi a settimana non significa che abbiamo un'intera settimana per elaborare quei messaggi.
=============== modifica:
Informazioni aggiuntive
Sulla base dei commenti, aggiungerò alcuni chiarimenti:
Non sono sicuro che la serializzazione sia il nostro collo di bottiglia. Ho confrontato l'applicazione e, sebbene la serializzazione sia presente nel grafico termico, è responsabile solo del 2,5-3% dell'utilizzo della CPU del servizio.
Sono principalmente preoccupato per la permanenza dei nostri messaggi e il potenziale uso improprio di MSMQ. Stiamo usando messaggi non transazionali e non persistenti in modo da poter continuare ad accodare le prestazioni e mi piacerebbe davvero avere messaggi almeno persistenti in modo che sopravvivessero al riavvio.
L'aggiunta di più RAM è una misura di stopgap. La macchina è già passata da 4 GB -> 16 GB di RAM e diventa sempre più difficile smontarla per continuare ad aggiungere altro.
A causa del modello di instradamento a stella dell'applicazione, metà del tempo in cui un oggetto viene espulso, quindi spinto in una coda, non cambia affatto. Questo si presta di nuovo (IMO) a memorizzarlo in una sorta di archivio di valori-chiave altrove e semplicemente a passare identificatori di messaggi.
Il modello di instradamento a stella è parte integrante dell'applicazione e non cambierà. Non siamo in grado di forzare l'applicazione perché ogni pezzo lungo la strada funziona in modo asincrono (in modo polling) e vogliamo centralizzare il comportamento dei tentativi in un unico posto.
La logica dell'applicazione è scritta in C #, gli oggetti sono POCO immutabili, l'ambiente di distribuzione di destinazione è Windows Server 2012 e siamo autorizzati a mettere in piedi macchine aggiuntive se un particolare software è supportato solo in Linux.
I miei obiettivi sono di mantenere l'attuale throughput riducendo al contempo l'ingombro della memoria e aumentando la tolleranza agli errori con un esborso minimo di capitale.