Εκτέλεση SpringBoot 2 - σερβέτα σερβέτ ενάντια στην ενεργό στοίβα WebFlux

Το Spring-boot 2.0 κυκλοφόρησε πρόσφατα και όλοι είναι ενθουσιασμένοι με τα νέα χαρακτηριστικά και τις βελτιώσεις.
Λατρεύω την ευκολία και την απλότητα με την οποία το Spring-boot σάς επιτρέπει να δημιουργείτε υπηρεσίες με ελάχιστη αναστάτωση.
Ένα από τα πιο ενδιαφέροντα, κρίσιμα και αξιοσημείωτα χαρακτηριστικά είναι η προσθήκη και η υποστήριξη μοντέλου αντιδραστικού προγραμματισμού.
Η Spring 5 εισήγαγε το πλαίσιο WebFlux, το οποίο είναι μια πλήρως ασύγχρονη και μη μπλοκαρισμένη στοίβα αντιδραστικών web που επιτρέπει τον χειρισμό τεράστιου αριθμού ταυτόχρονων συνδέσεων. Αυτό μας επιτρέπει να κατατάξουμε κάθετα την υπηρεσία για να χειριστούμε περισσότερο φορτίο στο ίδιο υλικό.

Ο σκοπός αυτού του πειράματος ήταν να συγκριθεί η παραδοσιακή στοίβα servlet με την ενεργό στοίβα, καταγράφοντας τις επιδόσεις υπό φορτίο.

Για να το πετύχω αυτό, δημιούργησα 3 υπηρεσίες ως εξής:
* Μια υπηρεσία PersonService βασισμένη σε web spring-boot 1.5.10.RELEASE
* Μια δεύτερη PersonService βασισμένη σε web 2.0.0.RELEASE
* Μια τρίτη υπηρεσία PersonService βασισμένη σε εφεδρική εκκίνηση-web-2.0.0.RELEASE. Για να διατηρήσω τον κώδικα όσο το δυνατόν πιο παρόμοιο, έχω χρησιμοποιήσει την προσέγγιση που βασίζεται σε σχολιασμούς για να δημιουργήσω παρόμοιους «ελεγκτές» και «υπηρεσίες». (Για τους περίεργους, υπάρχει ένας άλλος λειτουργικός τρόπος για να δημιουργήσετε διαδρομές και χειριστές).

Η πραγματική ισχύς της ενεργού στοίβας βγαίνει στην αλληλεπίδραση με την παρεμπόδιση I / O. Για να το προσομοιώσω, έχω προσθέσει μια υπηρεσία εγγραφής που εισάγει μια καθυστέρηση 200ms. Κάθε PersonService (ες) θα καλέσει το statusService και την κατάσταση επιστροφής 201-Δημιουργήθηκε αν είναι επιτυχής.

Για τη μέτρηση της απόδοσης, χρησιμοποίησα το Gatling για να γράψω το σενάριο δοκιμής μου. Η δοκιμή αποτελείται από ένα χρήστη καλώντας το personService 4 φορές με το ωφέλιμο φορτίο προσώπου (POST). Θα αλλάξουμε τον αριθμό των ταυτόχρονων χρηστών για να δούμε πώς συμπεριφέρεται η servlet έναντι της ενεργού στοίβας.

Το έργο είναι διαθέσιμο εδώ https://github.com/raj-saxena/spring-boot-1-vs-2-performance

Εδώ είναι τα ευρήματά μου:
(Διαπίστωσα ότι η απόδοση του ιστού 1.5.10.RELEASE και της εκκίνησης άνοιξη-εκκίνησης 2.0.0.RELEASE είναι ως επί το πλείστον παρόμοια, έτσι ώστε να μοιράζονται μόνο το αποτέλεσμα του web 2.0 άνοιξη-εκκίνησης boot vs spring-boot αντιδραστική- web-2.0.0.RELEASE Έχω προσθέσει τις αναφορές του τρέξιμου μου στο git repo επίσης).

Δοκιμάστε ταυτόχρονα 2500 χρήστες

SpringBoot 2 Servlet vs Αντιδραστική απόδοση - 2500 χρήστες (4 αιτήματα / χρήστης)

Μπορούμε να δούμε ότι οι χρόνοι απόκρισης είναι παρόμοιοι για αυτό το φορτίο, αλλά ο αριθμός αιτήσεων / δευτερόλεπτα που χειρίζεται η ενεργός στοίβα είναι περισσότερο από 1,5 φορές εκείνη της στοίβας servlet.

Αναφορές για την απόδοση σέρβερ του SpringBoot εδώ και αναφορές για την απόδοση του SpringBoot Reactive εδώ.

Δοκιμή για ταυτόχρονη χρήση 5000 χρηστών

SpringBoot 2 Servlet vs Αντιδραστική απόδοση - 5000 χρήστες (4 αιτήσεις / χρήστης)

Αρχίζει να γίνεται σαφές ότι η αντιδραστική στοίβα έχει καλύτερη απόδοση τόσο από την άποψη του χρόνου απόκρισης όσο και από τον αριθμό αιτήσεων / sec που μπορεί να χειριστεί.

Αναφορές για την απόδοση σέρβερ του SpringBoot εδώ και αναφορές για την απόδοση του SpringBoot Reactive εδώ.

Δοκιμάστε ταυτόχρονα 10000 χρήστες

SpringBoot 2 Servlet vs Αντιδραστική απόδοση - 10000 χρήστες (4 αιτήματα / χρήστης)

Μέχρι τώρα, μπορούμε να δούμε ότι η Reactive stack είναι ο σαφής νικητής.

Ενώ η απόδοση έχει υποβαθμιστεί ελαφρώς για την ενεργό στοίβα, υπάρχει τεράστια υποβάθμιση της απόδοσης για τη στοίβα servlet. Έχει σχεδόν μειωθεί ~ 8-10 φορές για το 50ο και 75ο εκατοστημόριο των αιτημάτων. Ορισμένα αιτήματα απέτυχαν κάθε φορά κατά τη διάρκεια πολλαπλών δοκιμών με τη στοίβα servlet.

Αναφορές για την απόδοση σέρβερ του SpringBoot εδώ και αναφορές για την απόδοση του SpringBoot Reactive εδώ.

Συμπέρασμα:

Μπορούμε να διαπιστώσουμε σαφώς ότι το φορτίο που η δραστική στοίβα μπορεί να αντέξει χωρίς απώλεια επιδόσεων είναι μια σημαντική βελτίωση. Μας επιτρέπει να αξιοποιήσουμε καλύτερα το υλικό ειδικά για υπηρεσίες που πραγματοποιούν πολλές λειτουργίες Ι / Ο όπως κάνοντας κλήσεις δικτύου σε άλλες υπηρεσίες ή αλληλεπιδρώντας με βάσεις δεδομένων. Έχει παρόμοια απόδοση υπό χαμηλό φορτίο και χειρίζεται γρήγορα το υψηλό φορτίο. Αυτή είναι μια μεγάλη νίκη!

Ωστόσο, η εργασία με το αντιδραστικό ρεύμα περιλαμβάνει μια μικρή καμπύλη μάθησης και εξασφαλίζοντας ότι κανένας προγραμματιστής δεν θα καταλήξει να αποκαλεί `block ()`. Ένας άλλος διακόπτης μπορεί να είναι η έλλειψη αντιδραστικών οδηγών βάσης δεδομένων. Το JDBC μπλοκάρει εγγενώς και πολύ λίγες άλλες βάσεις δεδομένων όπως η MongoDB, η Cassandra υποστηρίζουν επίσημα τους οδηγούς σε αυτό το σημείο.

Επιτρέψτε μου να γνωρίζω τις σκέψεις σας.

Εξοπλισμός που χρησιμοποιείται:
Επεξεργαστής: 2,3 GHz Intel Core i5
Μνήμη: 16 GB 2133 MHz LPDDR3
Γραφικά: Intel Iris Plus Graphics 640 1536 MB
Σας ενθαρρύνω να δοκιμάσετε τον εαυτό σας με διαφορετικό αριθμό χρηστών και να μοιραστείτε το αποτέλεσμα.

Μια σημείωση: Η καταγραφή της απόδοσης είναι ένα πολύ περίπλοκο και λεπτομερές πεδίο. Περιλαμβάνει πολλές παραμέτρους που μπορούν να επηρεάσουν τα αποτελέσματα. Έτρεξα τις δοκιμές πολλές φορές πριν τη σύλληψη, έτσι ώστε τα πράγματα όπως το ζέσταμα της JVM, η βελτιστοποίηση κώδικα byte κλπ να μην μεταβάλλουν τα αποτελέσματα. Προσπάθησα να ελαχιστοποιήσω τις μεταβλητές και να απλοποιήσω την εφαρμογή και να διατηρήσω τις συνθήκες δοκιμών όσο το δυνατόν περισσότερο. Παρόλο που ορίζω μεγάλο αριθμό ταυτόχρονων χρηστών, ο πραγματικός αριθμός αιτήσεων ανά δευτερόλεπτο περιορίζεται από την ικανότητα του υλικού μου. Αλλά, χρησιμεύει για να μας δώσει μια αίσθηση του πώς οι δύο στοίβες εκτελούν το άγχος.