Supponiamo che io stia scrivendo una libreria in Java per eseguire chiamate di rete. Voglio che sia efficiente per i casi come proxy inversi altamente caricati ecc (da 10 a 100 Krps che entrano ed escono, richieste client servite nello stesso DC in meno di 1 ms, elaborazione relativamente semplice dei risultati), inoltre, ogni richiesta in arrivo potrebbe iniziare diversi in uscita e combinare i risultati in modo semplice.
La libreria utilizza internamente socket client non bloccanti, ma voglio esporre qualche astrazione di livello superiore agli utenti di questa libreria. Ho iniziato con CompletableFuture
, ma mi sembra che possa generare troppa spazzatura: ogni "composizione" ( thenCompose
ecc.) Crea un nuovo oggetto; inoltre, incoraggia l'uso di lambda che sono anche oggetti separati (giusto?). Il futuro finale potrebbe consistere in diverse fasi (3-5 in realtà: raccoglie, tentativi ecc.), Quindi sembra un po 'troppi oggetti per richiesta.
Quali altre opzioni ho che fornirebbero almeno una certa "composibilità" (leggi: può essere usata dai client di libreria, e forse dalla libreria stessa) ma genererà meno spazzatura?
È possibile avere un ciclo di eventi "riutilizzabile" di sorta? Oppure il paradigma del flusso (reattivo) può aiutare? Si dicono cose positive sulle coroutine che sono equiparate alle macchine di stato per le lingue che non le supportano in modo nativo, ma ho difficoltà a immaginare come l'implementazione potrebbe anche sembrare per uno scenario come "chiama diversi servizi con riprova, una volta terminato alcuni / tutti, restituisce un risultato, fornisce un mezzo per i client della libreria che possono attingere a ciò o migliorarlo "... Potremmo avere un numero di processori collegati da code (che bloccano la coda nella forma più semplice), ma ho dei dubbi su l'efficienza di tale sistema: queste code non arrivano gratis, ci saranno elementi aggiunti, elementi tagliati, tutti questi migreranno attraverso l'intero "gasdotto" ... O forse Disruptor è la mia unica speranza? (Non che io capisca come applicarlo qui.)
Per questi approcci lo pseudocodice o uno schema che descrive come potrebbe funzionare o un collegamento a una spiegazione è molto apprezzato perché in qualche modo li conosco "su" ma non capisco come usarli o se funzioneranno nel mio Astuccio. O forse c'è un approccio ancora migliore che ho completamente perso? ..
Modifica: ho dimenticato di dire che in realtà sto estendendo una libreria di rete esistente per supportare l'utilizzo asincrono. La libreria riutilizza molto gli oggetti (buffer, socket, oggetti di risposta, ecc.), Quindi, in primo luogo, ho pensato che forse era davvero importante in questo contesto; in secondo luogo, mi piacerebbe perseguire gli stessi obiettivi di progettazione, se possibile.
Alcuni calcoli sul retro della busta che supportano questo desiderio: supponiamo che ci siano 4 futures per richiesta (quello originale, riprovare la logica, raccogliere diversi risultati logici e quindi logica client). Supponiamo che ci siano 50.000 richieste di server in arrivo al secondo e ciascuna si traduce in 2 richieste client. Quindi questo è già 4 * 2 * 50_000 * (object_size)
byte al secondo supponendo che i callback vengano riutilizzati. Supponiamo che ogni oggetto abbia 20 byte (intestazione, almeno un listener, riferimento al risultato). Supponi che i callback vengano riutilizzati in modo tale che non vengano creati e raccolti. Questo è 8 Mb al secondo, ma facilmente di più. Quello è 1 GB di spazzatura per un paio di minuti. Forse non troppo, davvero, ma sarebbe comunque interessante capire se potesse essere migliorato.