Come progettare un semplice server UDP in grado di gestire 10000 req / sec?

3

Attualmente ho implementato un semplice server UDP usando i socket java, non appena il pacchetto viene ricevuto viene aggiunto alla coda e ci sono quattro thread di consumo che elaborano la coda.

Questo approccio va bene fino a 10000 req / sec, ma c'è una significativa perdita di pacchetti di pacchetti poiché il numero di pacchetti / sec è > 10000 req / sec.

Dopo un'attenta analisi i motivi sono le code, a causa della latenza di aggiungere il pacchetto alla coda e blocchi socket.receive finché il pacchetto non viene aggiunto alla coda

Utilizzato anche il canale del datagramma che non è IO bloccante, ma i risultati sono più poveri dell'IO di blocco (java socket). Ecco il codice di esempio

try (DatagramSocket socket = new DatagramSocket(port)) {
            System.out.println("Udp Server started at port :" + port);


            while (true) {
                byte[] buffer = new byte[1024];
                DatagramPacket incomingDatagramPacket = new DatagramPacket(buffer, buffer.length);
                try {
                    socket.receive(incomingDatagramPacket);
                    LinkedTransferQueue.add(incomingDatagramPacket);
                } catch (IOException e) {
                    e.printStackTrace();
                    continue;

                }


            }

        } catch (SocketException e) {
            e.printStackTrace();
        }

C'è un altro modo comprovato per progettare il server UDP in un modo migliore?

    
posta forum.test17 20.08.2018 - 23:37
fonte

1 risposta

5

Non hai notato se la latenza è dovuta alla profondità della coda o se è il tempo che impiega per entrare in coda da sola. C'è una legge ferrea sull'accodamento: se la velocità complessiva dei messaggi in arrivo supera la velocità complessiva dei messaggi di consumo, la profondità della coda aumenterà nel tempo. La dimensione massima della coda è semplicemente un buffer che consente uno squilibrio temporaneo. Stai utilizzando una coda illimitata ma ci sono dei limiti impliciti. Man mano che si aumenta la coda, è necessario allocare memoria e questo richiede tempo. Ad un certo punto, non ci sarà più memoria disponibile e questo è il tuo limite. Hai bisogno che i consumatori leggano più velocemente di quello che scrivi. Quindi, se i tuoi consumatori non riescono a tenere il passo, devi ridimensionare a più consumatori. Se i tuoi consumatori sono vincolati all'IO, considera le opzioni NIO. Se sono collegati alla CPU, sono necessari più thread / core / server.

Se la coda è di per sé il collo di bottiglia, potresti prendere in considerazione la Disruptor struttura dati che è stato sviluppato come parte del progetto LMAX . Sostengono che può ottenere un throughput molto più elevato. Se non altro, imparerai qualche ingegnerizzazione del software davvero intelligente. L'idea principale qui è che la progettazione di una coda impone l'invalidazione della cache L3 eccessiva e la struttura Disruptor lo evita.

    
risposta data 20.08.2018 - 23:58
fonte

Leggi altre domande sui tag