Supponiamo che ogni attività (attività di elaborazione correlata all'elemento dei dati) termini in una coda sul server. Per ottenere i 20 lavori al minuto in modo semplice, è possibile impostare un'attività ricorrente, che ogni minuto preleva al massimo 20 elementi dalla coda di input e li inserisce in una coda di elaborazione, che viene quindi elaborata da 1 o più filettature.
Il modo in cui lo fai dipende dal tuo ecosistema e dall'ambiente di programmazione.
In F #, ad esempio, potresti usare MailboxProcessor<>
da FSharp.Control
namespace per creare uno stile di soluzione per attore, facendo proprio questo. In C #, è possibile utilizzare il modello Task. Su Pony (sì, questo è anche un linguaggio di programmazione;)), potresti usare gli attori (come tutto ciò che fai lì, è usare gli attori). In ambienti C / C ++ piuttosto bassi, è possibile allocare un piccolo pool di thread (1.una frazione del numero dei core del server), che quindi estraggono le loro attività dalla coda di elaborazione (furto del lavoro). E così via.
Questo produce ancora picchi di carico sul tuo server, poiché ogni minuto funzionerà in modo aggressivo sulle attività di elaborazione degli elementi programmati.
Se si desidera ottenere un carico di fondo più bilanciato entro il lasso di tempo di 1 minuto, è necessario prendere in considerazione ulteriori dettagli sul codice di elaborazione. Se, ad esempio, il tempo di elaborare 1 elemento è piuttosto costante e non molto variabile nella complessità di elaborazione, è possibile eseguire una stima dinamica del tempo di elaborazione per 1 elemento e quindi tracciare i 20 elementi dalla coda di input, solo per pianificare una frazione di essi ogni 60/20 = 3 secondi (alcune attività precedenti potrebbero ancora essere in esecuzione, dato che il server ha anche altre cose da fare e il suo carico di lavoro non è costante). Quanti da pianificare è quindi l'obiettivo dello stimatore.
L'ultimo problema rimasto di cui preoccuparsi è la contropressione. Se si limita strongmente la velocità di elaborazione degli articoli, ma l'afflusso di nuove attività è fuori dal controllo di questi server, la coda di input aumenterà senza limiti. Quindi, piuttosto, proverei a limitare l'elaborazione più o meno, a seconda della lunghezza della coda di input. Oppure aggiungi una reale contropressione alla comunicazione client / server. Ad esempio, chiedi al tuo server di richiedere 20 articoli ogni minuto (in un batch) invece di mandare il client al server come preferisci.
A meno che non si tratti di una sorta di progetto di ricerca o ci siano altre ragioni interessanti, non prenderei in considerazione l'idea di diventare troppo sofisticato su questo problema. Mantenerlo semplice approccio ti fa risparmiare tempo, linee di codice (e in quanto tale, potenziali bug) e in casi estremi l'aspetto divertente dei tuoi colleghi (se sei andato fuori bordo con la tua soluzione).
Se in realtà si programma il lato client (e non il lato server come ho supposto sopra) e se il codice del server ha fatto cattive scelte di vita (nessuna contropressione nel protocollo), si può ancora fare ciò che ho descritto sopra per ottenere il vostro strozzamento. Quello che ho chiamato la coda di input sopra sarebbe ora la tua coda di uscita. E il tuo compito, che è pianificato una volta al minuto, ora richiama al massimo 20 elementi dalla coda di output e li invia come batch al server.