Πώς το Quarkus συνδυάζει επιτακτικό και αντιδραστικό προγραμματισμό

Φέτος σχεδιάζουμε να αναπτύξουμε σοβαρά θέματα κοντέινερ, Cloud-Native Java и Kubernetes. Μια λογική συνέχεια αυτών των θεμάτων θα είναι ήδη μια ιστορία για το πλαίσιο του Quarkus θεωρούνται στο Habré. Το σημερινό άρθρο αφορά λιγότερο τον σχεδιασμό της «υποατομικής υπερταχείας Java» και περισσότερο την υπόσχεση που φέρνει το Quarkus στο Enterprise.

Πώς το Quarkus συνδυάζει επιτακτικό και αντιδραστικό προγραμματισμό

Η Java και το JVM εξακολουθούν να είναι εξαιρετικά δημοφιλή, αλλά όταν εργάζεστε με τεχνολογίες χωρίς διακομιστή και μικροϋπηρεσίες εγγενούς στο cloud, η Java και άλλες γλώσσες JVM χρησιμοποιούνται όλο και λιγότερο επειδή καταλαμβάνουν πολύ χώρο στη μνήμη και είναι πολύ αργές στη φόρτωσή τους. ακατάλληλο για χρήση με δοχεία μικρής διάρκειας. Ευτυχώς, αυτή η κατάσταση αρχίζει τώρα να αλλάζει χάρη στο Quarkus.

Η Superfast υποατομική Java έχει φτάσει σε νέο επίπεδο!

42 κυκλοφορίες, 8 μήνες κοινοτικής εργασίας και 177 καταπληκτικοί προγραμματιστές - το αποτέλεσμα όλων ήταν η κυκλοφορία τον Νοέμβριο του 2019 Κουάρκους 1.0, μια κυκλοφορία που σηματοδοτεί ένα σημαντικό ορόσημο στην ανάπτυξη του έργου και προσφέρει πολλές δροσερές δυνατότητες και δυνατότητες (μπορείτε να διαβάσετε περισσότερα για αυτές στο ανακοίνωση).

Σήμερα θα σας δείξουμε πώς το Quarkus συνδυάζει επιτακτικά και αντιδραστικά μοντέλα προγραμματισμού σε έναν μόνο αντιδραστικό πυρήνα. Θα ξεκινήσουμε με ένα σύντομο ιστορικό και στη συνέχεια θα δούμε λεπτομερώς τι είναι ο αντιδραστικός πυρήνας δυϊσμός του Quarkus και πώς Java-Οι προγραμματιστές μπορούν να επωφεληθούν από αυτά τα οφέλη.

Μικροϋπηρεσίες, αρχιτεκτονικές που βασίζονται σε γεγονότα и χωρίς διακομιστή-λειτουργίες – όλα αυτά είναι, όπως λένε, σε άνοδο σήμερα. Πρόσφατα, η δημιουργία αρχιτεκτονικών με επίκεντρο το cloud έχει γίνει πολύ πιο εύκολη και πιο προσιτή, αλλά τα προβλήματα παραμένουν - ειδικά για τους προγραμματιστές Java. Για παράδειγμα, στην περίπτωση λειτουργιών χωρίς διακομιστή και μικροϋπηρεσιών, υπάρχει επείγουσα ανάγκη να μειωθεί ο χρόνος εκκίνησης, να μειωθεί η κατανάλωση μνήμης και να γίνει η ανάπτυξή τους πιο βολική και ευχάριστη. Η Java έχει κάνει αρκετές βελτιώσεις τα τελευταία χρόνια, όπως βελτιωμένη εργονομική λειτουργικότητα για κοντέινερ και ούτω καθεξής. Ωστόσο, η σωστή λειτουργία της Java σε ένα κοντέινερ εξακολουθεί να είναι πρόκληση. Θα ξεκινήσουμε λοιπόν εξετάζοντας μερικές από τις εγγενείς πολυπλοκότητες της Java, οι οποίες είναι ιδιαίτερα έντονες κατά την ανάπτυξη εφαρμογών Java που προσανατολίζονται σε κοντέινερ.

Αρχικά, ας δούμε την ιστορία.

Πώς το Quarkus συνδυάζει επιτακτικό και αντιδραστικό προγραμματισμό

Ρεύματα και κοντέινερ

Ξεκινώντας με την έκδοση 8u131, η Java άρχισε να υποστηρίζει λίγο πολύ τα κοντέινερ λόγω βελτιώσεων στη λειτουργικότητα της εργονομίας. Ειδικότερα, το JVM γνωρίζει πλέον σε πόσους πυρήνες επεξεργαστή εκτελείται και μπορεί να διαμορφώσει τις ομάδες νημάτων —συνήθως ομάδες διακλάδωσης/σύνδεσης—ανάλογα. Φυσικά, αυτό είναι υπέροχο, αλλά ας πούμε ότι έχουμε μια παραδοσιακή διαδικτυακή εφαρμογή που χρησιμοποιεί servlets HTTP και εκτελείται σε Tomcat, Jetty κ.λπ. Ως αποτέλεσμα, αυτή η εφαρμογή θα δώσει σε κάθε αίτημα ένα ξεχωριστό νήμα και θα του επιτρέψει να αποκλείσει αυτό το νήμα ενώ περιμένει για λειτουργίες I/O, για παράδειγμα, κατά την πρόσβαση στη βάση δεδομένων, αρχεία ή άλλες υπηρεσίες. Δηλαδή, το μέγεθος μιας τέτοιας εφαρμογής δεν εξαρτάται από τον αριθμό των διαθέσιμων πυρήνων, αλλά από τον αριθμό των ταυτόχρονων αιτημάτων. Επιπλέον, αυτό σημαίνει ότι οι ποσοστώσεις ή τα όρια στο Kubernetes στον αριθμό των πυρήνων δεν θα βοηθήσουν πολύ εδώ, και το θέμα θα καταλήξει τελικά σε στραγγαλισμό.

Εξάντληση μνήμης

Τα νήματα είναι μνήμη. Και οι περιορισμοί μνήμης εντός του κοντέινερ δεν είναι σε καμία περίπτωση πανάκεια. Απλώς αρχίστε να αυξάνετε τον αριθμό των εφαρμογών και των νημάτων και αργά ή γρήγορα θα αντιμετωπίσετε μια κρίσιμη αύξηση στη συχνότητα μεταγωγής και, ως αποτέλεσμα, υποβάθμιση της απόδοσης. Επίσης, εάν η εφαρμογή σας χρησιμοποιεί παραδοσιακά πλαίσια microservice ή συνδέεται σε μια βάση δεδομένων, ή χρησιμοποιεί προσωρινή αποθήκευση ή με άλλον τρόπο χρησιμοποιεί μνήμη, προφανώς χρειάζεστε ένα εργαλείο που σας επιτρέπει να κοιτάξετε μέσα στο JVM και να δείτε πώς διαχειρίζεται τη μνήμη χωρίς να τη σκοτώνει. Το ίδιο το JVM (για παράδειγμα, XX:+UseCGroupMemoryLimitForHeap). Και παρόλο που, από την Java 9, το JVM έμαθε να δέχεται cgroups και να προσαρμόζεται ανάλογα, η κράτηση και η διαχείριση της μνήμης παραμένει ένα αρκετά περίπλοκο θέμα.

Ποσοστώσεις και όρια

Η Java 11 εισήγαγε υποστήριξη για ποσοστώσεις CPU (όπως το PreferContainerQuotaForCPUCount). Το Kubernetes προσφέρει επίσης υποστήριξη για όρια και ποσοστώσεις. Ναι, όλα αυτά είναι λογικά, αλλά αν η εφαρμογή υπερβεί ξανά το εκχωρημένο όριο, καταλήγουμε πάλι στο μέγεθος - όπως συμβαίνει με τις παραδοσιακές εφαρμογές Java - που καθορίζεται από τον αριθμό των πυρήνων και με την κατανομή ενός ξεχωριστού νήματος για κάθε αίτημα, τότε δεν έχει νόημα όλο αυτό.
Επιπλέον, εάν χρησιμοποιείτε ποσοστώσεις και όρια ή τις λειτουργίες κλιμάκωσης της πλατφόρμας που βρίσκεται κάτω από το Kubernetes, το πρόβλημα επίσης δεν λύνεται από μόνο του. Απλώς ξοδεύουμε περισσότερους πόρους για την επίλυση του αρχικού προβλήματος ή καταλήγουμε σε υπερβολικές δαπάνες. Και αν πρόκειται για ένα σύστημα υψηλού φορτίου σε ένα δημόσιο δημόσιο σύννεφο, σχεδόν σίγουρα καταλήγουμε να χρησιμοποιούμε περισσότερους πόρους από αυτούς που πραγματικά χρειαζόμαστε.

Και τι να τα κάνεις όλα αυτά;

Για να το θέσω απλά, χρησιμοποιήστε ασύγχρονες και μη αποκλειστικές βιβλιοθήκες εισόδου/εξόδου και πλαίσια όπως το Netty, Vert.x ή Άκκα. Είναι πολύ πιο κατάλληλα για εργασία σε δοχεία λόγω της αντιδραστικής φύσης τους. Χάρη στις μη αποκλειστικές εισόδους/εξόδους, το ίδιο νήμα μπορεί να επεξεργαστεί πολλαπλές ταυτόχρονες αιτήσεις. Ενώ ένα αίτημα περιμένει τα αποτελέσματα I/O, το νήμα που το επεξεργάζεται απελευθερώνεται και αναλαμβάνεται από ένα άλλο αίτημα. Και όταν τελικά φτάσουν τα αποτελέσματα I/O, η επεξεργασία του πρώτου αιτήματος συνεχίζεται. Με την παρεμβαλλόμενη επεξεργασία αιτημάτων εντός του ίδιου νήματος, μπορείτε να μειώσετε τον συνολικό αριθμό των νημάτων και να μειώσετε την κατανάλωση πόρων για την επεξεργασία αιτημάτων.

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

Πώς, είναι όλο αυτό;

Όχι, υπάρχει κάτι άλλο. Ο αντιδραστικός προγραμματισμός βοηθά στην καλύτερη χρήση των πόρων, αλλά έχει και ένα τίμημα. Συγκεκριμένα, ο κώδικας θα πρέπει να ξαναγραφτεί σύμφωνα με τις αρχές του μη αποκλεισμού και να αποφευχθεί ο αποκλεισμός νημάτων I/O. Και αυτό είναι ένα εντελώς διαφορετικό μοντέλο ανάπτυξης και εκτέλεσης. Και παρόλο που υπάρχουν πολλές χρήσιμες βιβλιοθήκες εδώ, εξακολουθεί να είναι μια ριζική αλλαγή στον συνηθισμένο τρόπο σκέψης.

Πρώτα, πρέπει να μάθετε πώς να γράφετε κώδικα που εκτελείται ασύγχρονα. Μόλις αρχίσετε να χρησιμοποιείτε I/O χωρίς αποκλεισμό, πρέπει να προσδιορίσετε ρητά τι θα συμβεί όταν ληφθεί μια απάντηση σε ένα αίτημα. Ο απλός αποκλεισμός και η αναμονή δεν θα λειτουργούν πλέον. Αντίθετα, μπορείτε να μεταβιβάσετε επιστροφές κλήσης, να χρησιμοποιήσετε τον αντιδραστικό προγραμματισμό ή τη συνέχιση. Αλλά δεν είναι μόνο αυτό: για να χρησιμοποιήσετε I/O χωρίς αποκλεισμό, χρειάζεστε τόσο διακομιστές όσο και πελάτες χωρίς αποκλεισμό, κατά προτίμηση παντού. Στην περίπτωση του HTTP, όλα είναι απλά, αλλά υπάρχουν επίσης βάσεις δεδομένων, συστήματα αρχείων και πολλά άλλα.

Και παρόλο που η συνολική αντιδραστικότητα από άκρο σε άκρο μεγιστοποιεί την αποτελεσματικότητα, μια τέτοια μετατόπιση μπορεί να είναι δύσκολη στην πράξη. Επομένως, η δυνατότητα συνδυασμού αντιδραστικού και επιτακτικού κώδικα γίνεται απαραίτητη προϋπόθεση για:

  1. Χρησιμοποιήστε αποτελεσματικά τους πόρους στις πιο φορτισμένες περιοχές του συστήματος λογισμικού.
  2. Χρησιμοποιήστε απλούστερο κώδικα στυλ στα υπόλοιπα μέρη του.

Παρουσίαση του Quarkus

Στην πραγματικότητα, αυτή είναι η ουσία του Quarkus - να συνδυάζει αντιδραστικά και επιτακτικά μοντέλα σε ένα ενιαίο περιβάλλον χρόνου εκτέλεσης.

Το Quarkus βασίζεται στο Vert.x και στο Netty, με μια σειρά από αντιδραστικά πλαίσια και επεκτάσεις στην κορυφή για να βοηθήσουν τον προγραμματιστή. Το Quarkus έχει σχεδιαστεί για τη δημιουργία όχι μόνο μικροϋπηρεσιών HTTP, αλλά και αρχιτεκτονικών που βασίζονται σε εκδηλώσεις. Λόγω της αντιδραστικής φύσης του, λειτουργεί πολύ αποτελεσματικά με συστήματα ανταλλαγής μηνυμάτων (Apache Kafka, AMQP κ.λπ.).

Το κόλπο είναι πώς να χρησιμοποιήσετε τον ίδιο αντιδραστικό κινητήρα τόσο για επιτακτικούς όσο και για αντιδραστικό κώδικα.

Πώς το Quarkus συνδυάζει επιτακτικό και αντιδραστικό προγραμματισμό

Το Quarkus το κάνει έξοχα. Η επιλογή μεταξύ επιτακτικού και αντιδραστικού είναι προφανής - χρησιμοποιήστε έναν αντιδραστικό πυρήνα και για τα δύο. Αυτό που πραγματικά βοηθάει είναι ο γρήγορος, μη αποκλειστικός κώδικας που χειρίζεται σχεδόν οτιδήποτε περνά μέσα από το νήμα βρόχου συμβάντων, γνωστό και ως νήμα IO. Αλλά αν διαθέτετε κλασικές εφαρμογές REST ή εφαρμογές πελάτη, το Quarkus έχει έτοιμο ένα επιτακτικό μοντέλο προγραμματισμού. Για παράδειγμα, η υποστήριξη HTTP στο Quarkus βασίζεται στη χρήση ενός μη αποκλειστικού και αντιδραστικού κινητήρα (Eclipse Vert.x και Netty). Όλα τα αιτήματα HTTP που λαμβάνονται από την εφαρμογή σας περνούν πρώτα μέσω ενός βρόχου συμβάντων (IO Thread) και στη συνέχεια αποστέλλονται στο τμήμα του κώδικα που διαχειρίζεται τα αιτήματα. Ανάλογα με τον προορισμό, ο κωδικός διαχείρισης αιτήματος μπορεί να κληθεί μέσα σε ένα ξεχωριστό νήμα (το λεγόμενο νήμα εργάτη, που χρησιμοποιείται στην περίπτωση των servlets και του Jax-RS) ή να χρησιμοποιήσει το νήμα I/O πηγής (αντιδραστική διαδρομή).

Πώς το Quarkus συνδυάζει επιτακτικό και αντιδραστικό προγραμματισμό

Οι υποδοχές συστήματος ανταλλαγής μηνυμάτων χρησιμοποιούν υπολογιστές-πελάτες χωρίς αποκλεισμό που εκτελούνται πάνω από τη μηχανή Vert.x. Επομένως, μπορείτε αποτελεσματικά να στέλνετε, να λαμβάνετε και να επεξεργάζεστε μηνύματα από συστήματα ενδιάμεσου λογισμικού ανταλλαγής μηνυμάτων.

Η ιστοσελίδα Quarkus.io Ακολουθούν μερικά καλά μαθήματα που θα σας βοηθήσουν να ξεκινήσετε με το Quarkus:

Έχουμε επίσης δημιουργήσει διαδικτυακά πρακτικά σεμινάρια για να σας διδάξουμε διάφορες πτυχές του αντιδραστικού προγραμματισμού μόνο σε ένα πρόγραμμα περιήγησης, δεν απαιτείται IDE και δεν απαιτείται υπολογιστής. Μπορείτε να βρείτε αυτά τα μαθήματα εδώ.

Χρήσιμοι πόροι

10 βίντεο μαθήματα για το Quarkus για εξοικείωση με το θέμα

Όπως λένε στην ιστοσελίδα Quarkus.io, Κουάρκος - Είναι Kubernetes- προσανατολισμένη στοίβα Java, προσαρμοσμένη για GraalVM και OpenJDK HotSpot και συναρμολογημένη από τις καλύτερες βιβλιοθήκες και πρότυπα Java.

Για να σας βοηθήσουμε να κατανοήσετε το θέμα, επιλέξαμε 10 εκπαιδευτικά βίντεο που καλύπτουν διάφορες πτυχές του Quarkus και παραδείγματα χρήσης του:

1. Παρουσιάζοντας το Quarkus: The Next Generation Java Framework για Kubernetes

Τους Thomas Qvarnstrom και Jason Greene
Ο στόχος του έργου Quarkus είναι να δημιουργήσει μια πλατφόρμα Java για Kubernetes και περιβάλλοντα χωρίς διακομιστή και να συνδυάσει αντιδραστικά και επιτακτικά μοντέλα προγραμματισμού σε ένα ενιαίο περιβάλλον χρόνου εκτέλεσης, έτσι ώστε οι προγραμματιστές να μπορούν να διαφοροποιούν ευέλικτα την προσέγγισή τους όταν εργάζονται με ένα ευρύ φάσμα κατανεμημένων αρχιτεκτονικών εφαρμογών. Μάθετε περισσότερα στην εισαγωγική διάλεξη παρακάτω.

2. Quarcus: Superfast Subatomic Java

Από: Burr Sutter
Αυτό το εκπαιδευτικό βίντεο από το DevNation Live δείχνει πώς να χρησιμοποιείτε το Quarkus για τη βελτιστοποίηση των εταιρικών εφαρμογών Java, των API, των microservices και των λειτουργιών χωρίς διακομιστή σε περιβάλλον Kubernetes/OpenShift, καθιστώντας τα πολύ μικρότερα, ταχύτερα και πιο επεκτάσιμα.

3. Quarkus και GraalVM: επιτάχυνση του Hibernate σε σούπερ ταχύτητες και συρρίκνωση του σε υποατομικά μεγέθη

Συγγραφέας: Sanne Grinovero
Από την παρουσίαση θα μάθετε πώς δημιουργήθηκε το Quarkus, πώς λειτουργεί και πώς σας επιτρέπει να κάνετε σύνθετες βιβλιοθήκες, όπως το Hibernate ORM, συμβατές με εγγενείς εικόνες GraalVM.

4. Μάθετε να αναπτύσσετε εφαρμογές χωρίς διακομιστή

Συγγραφέας: Martin Luther
Το παρακάτω βίντεο δείχνει πώς να δημιουργήσετε μια απλή εφαρμογή Java χρησιμοποιώντας το Quarkus και να την αναπτύξετε ως εφαρμογή χωρίς διακομιστή στο Knative.

5. Quarkus: Διασκεδάστε με την κωδικοποίηση

Συγγραφέας: Edson Yanaga
Ένας οδηγός βίντεο για τη δημιουργία του πρώτου σας έργου Quarkus, που σας επιτρέπει να κατανοήσετε γιατί το Quarkus κερδίζει τις καρδιές των προγραμματιστών.

6. Java και κοντέινερ - ποιο θα είναι το μέλλον τους μαζί

Δημοσιεύτηκε από τον Mark Little
Αυτή η παρουσίαση εισάγει την ιστορία της Java και εξηγεί γιατί το Quarkus είναι το μέλλον της Java.

7. Quarcus: Superfast Subatomic Java

Συγγραφέας: Δημήτρης Ανδρεάδης
Μια επισκόπηση των πλεονεκτημάτων του Quarkus που έχουν αναγνωριστεί από τους προγραμματιστές: απλότητα, εξαιρετικά υψηλές ταχύτητες, οι καλύτερες βιβλιοθήκες και πρότυπα.

8. Quarkus και υποατομικά πυραυλικά συστήματα

Συγγραφέας: Clement Escoffier
Μέσω της ενσωμάτωσης με το GraalVM, το Quarkus παρέχει μια εξαιρετικά γρήγορη εμπειρία ανάπτυξης και ένα υποατομικό περιβάλλον χρόνου εκτέλεσης. Ο συγγραφέας μιλά για την αντιδραστική πλευρά του Quarkus και τον τρόπο χρήσης του για τη δημιουργία reactive και streaming εφαρμογών.

9. Quarkus και γρήγορη ανάπτυξη εφαρμογών στο Eclipse MicroProfile

Συγγραφέας: John Clingan
Συνδυάζοντας το Eclipse MicroProfile και το Quarkus, οι προγραμματιστές μπορούν να δημιουργήσουν εφαρμογές MicroProfile με πλήρεις δυνατότητες που εκκινούν σε δεκάδες χιλιοστά του δευτερολέπτου. Το βίντεο περιγράφει λεπτομερώς τον τρόπο κωδικοποίησης μιας εφαρμογής MicroProfile με κοντέινερ για ανάπτυξη στην πλατφόρμα Kubernetes.

10. Java, έκδοση "Turbo".

Συγγραφέας: Marcus Biel
Ο συγγραφέας δείχνει πώς να χρησιμοποιήσετε το Quarkus για να δημιουργήσετε εξαιρετικά μικρά, εξαιρετικά γρήγορα κοντέινερ Java που επιτρέπουν πραγματικές ανακαλύψεις, ειδικά σε περιβάλλοντα χωρίς διακομιστή.



Πηγή: www.habr.com

Προσθέστε ένα σχόλιο