Asynchronous-IO vs Asynchronous-Request Processing στην Ιάβα

Σε αυτό το άρθρο, προσπαθώ να εξηγήσω τη διαφορά μεταξύ επεξεργασίας Async-IO και Async-Request στο αίτημα HTTP στον κόσμο της Java.

Στον προ-Java 1.4 κόσμο, η Java παρέχει ένα API για αποστολή / λήψη δεδομένων μέσω της υποδοχής δικτύου. Οι αρχικοί συντάκτες του JVM χαρτογράφησαν αυτήν τη συμπεριφορά API στο OS socket API, σχεδόν ένα προς ένα.

Λοιπόν, ποια είναι η συμπεριφορά της υποδοχής OS; Το OS παρέχει Socket προγραμματισμού api, το οποίο έχει μια κλήση αποκλεισμού αποστολής / λήψης . Δεδομένου ότι το java είναι απλώς μια διαδικασία που τρέχει πάνω από το linux (OS), ως εκ τούτου αυτό το πρόγραμμα java πρέπει να χρησιμοποιήσει αυτό το μπλοκ api που παρέχεται από το λειτουργικό σύστημα.

Ο κόσμος ήταν χαρούμενος και οι προγραμματιστές java άρχισαν να χρησιμοποιούν το API για την αποστολή / λήψη των δεδομένων. Αλλά έπρεπε να κρατήσουν ένα νήμα java για κάθε υποδοχή (πελάτης).

Όλοι έγραφαν τη δική τους γεύση διακομιστών HTTP. Η κοινή χρήση κώδικα γινόταν δύσκολη, ο κόσμος της java ζήτησε τυποποίηση.

Εισάγει την προδιαγραφή java servlet.

Πριν προχωρήσουμε ας ορίσουμε μερικούς όρους:

Java Server Developer : Άτομα που χρησιμοποιούν το java socket api και εφαρμόζουν πρωτόκολλο http όπως το tomcat.

java Application Developer: Άτομα που δημιουργούν την εφαρμογή επιχειρήσεων πάνω από το tomcat.

ΕΠΙΣΤΡΟΦΗ ΤΩΡΑ

Μόλις η προδιαγραφή java servlet μπήκε στον κόσμο, είπε:

Αγαπητοί προγραμματιστές διακομιστών java, δώστε μια μέθοδο όπως παρακάτω:

doGet(inputReq, OutPutRes)

έτσι ώστε ο προγραμματιστής εφαρμογών java να μπορεί να εφαρμόσει doGetκαι να μπορεί να γράψει τη λογική της επιχείρησής τους. Μόλις ο "προγραμματιστής εφαρμογών" θέλει να στείλει το response, μπορεί να καλέσειOutPutRes.write().

Ένα πράγμα που πρέπει να σημειωθεί: Δεδομένου ότι το socket api αποκλείει, επομένως το OutPutRes.write () αποκλείει επίσης. Επίσης, ο πρόσθετος περιορισμός ήταν ότι το αντικείμενο απόκρισης δεσμεύεται κατά την έξοδο της μεθόδου doGet .

Λόγω αυτών των περιορισμών, οι άνθρωποι έπρεπε να χρησιμοποιήσουν ένα νήμα για την επεξεργασία ενός αιτήματος.

Ο χρόνος πέρασε και το Διαδίκτυο ανέλαβε τον κόσμο. Ένα νήμα ανά αίτημα άρχισε να εμφανίζει περιορισμούς.

Πρόβλημα 1:

Το νήμα ανά αίτημα αποτυγχάνει όταν υπάρχουν μεγάλες παύσεις κατά την επεξεργασία κάθε αιτήματος.

Για παράδειγμα: η λήψη δεδομένων από την υπο-υπηρεσία διαρκεί πολύ χρόνο.

Σε μια τέτοια κατάσταση, το νήμα είναι κυρίως σε αδράνεια και το JVM μπορεί να ξεμείνει εύκολα από το νήμα.

Πρόβλημα 2:

Τα πράγματα έγιναν ακόμη χειρότερα με τη συνεχή σύνδεση http1.1. Όπως με την επίμονη σύνδεση, η υποκείμενη σύνδεση TCP θα διατηρηθεί ζωντανή και ο διακομιστής πρέπει να αποκλείσει ένα νήμα ανά σύνδεση.

Γιατί όμως ο διακομιστής πρέπει να αποκλείσει ένα νήμα ανά σύνδεση;

Εφόσον το OS παρέχει μια υποδοχή αποκλεισμού Recv api, το jvm πρέπει να καλέσει τη μέθοδο Recv blocking OS για να ακούσει περισσότερα αιτήματα στην ίδια σύνδεση tcp από τον πελάτη.

Ο κόσμος ζήτησε λύση!

Η πρώτη λύση προήλθε από τον δημιουργό του JVM. Εισήγαγαν το NIO ( ASYNC-IO ). Το Nio είναι το API μη αποκλεισμού για αποστολή / λήψη δεδομένων μέσω υποδοχής.

Κάποιο υπόβαθρο: τοΤο λειτουργικό σύστημα μαζί με το μπλοκ του socket api παρέχει επίσης μια μη αποκλεισμένη έκδοση του socket api.

Αλλά πώς το παρέχει αυτό το λειτουργικό σύστημα .. Διακλαδώνει ένα νήμα εσωτερικά και αυτό το νήμα μπλοκάρεται ???

Η ΑΠΑΝΤΗΣΗ είναι όχι… το λειτουργικό σύστημα δίνει εντολή στο υλικό να διακόπτεται όταν υπάρχουν δεδομένα για ανάγνωση ή εγγραφή.

Το NIO επέτρεψε στον " προγραμματιστή διακομιστή java"για την αντιμετώπιση του προβλήματος 2 του αποκλεισμού ενός νήματος ανά σύνδεση TCP . Με το NIO να είναι μόνιμη σύνδεση HTTP, το νήμα δεν το απαιτεί να μπλοκάρει στην κλήση recv . Αντ 'αυτού, μπορεί τώρα να το επεξεργαστεί μόνο όταν υπάρχουν δεδομένα για επεξεργασία. Αυτό επέτρεψε σε ένα νήμα να παρακολουθεί / χειρίζεται έναν μεγάλο αριθμό επίμονων συνδέσεων.

Η δεύτερη λύση προήλθε από servlet spec. Το Servlet Spec έλαβε μια αναβάθμιση και εισήγαγε την υποστήριξη async (Async Request Processing).

AsyncContext acontext = req.startAsync();
ΣΗΜΑΝΤΙΚΟ: Αυτή η αναβάθμιση αφαίρεσε τον περιορισμό της εκτέλεσης του αντικειμένου απόκρισης κατά την ολοκλήρωση της μεθόδου doGet .

Αυτό επέτρεψε στο " Java Application Developer" να αντιμετωπίσει το πρόβλημα 1, αποφορτώνοντας την εργασία σε νήματα στο παρασκήνιο. Τώρα αντί να διατηρείται το νήμα σε αναμονή κατά τη διάρκεια της μεγάλης παύσης, το νήμα μπορεί να χρησιμοποιηθεί για τον χειρισμό άλλων αιτημάτων.

ΣΥΜΠΕΡΑΣΜΑ:

Το Async-IO στο java χρησιμοποιεί βασικά την έκδοση χωρίς αποκλεισμό στο OS socket API.

Η επεξεργασία αιτήσεων Async είναι βασικά η τυποποίηση servlet spec για τον τρόπο επεξεργασίας περισσότερων αιτημάτων με ένα νήμα.

ΒΙΒΛΙΟΓΡΑΦΙΚΕΣ ΑΝΑΦΟΡΕΣ:

//www.scottklement.com/rpg/socktut/tutorial.pdf

//stackoverflow.com/questions/15217524/what-is-the-difference-between-thread-per-connection-vs-thread-per-request

Κίνητρο του άρθρου: Ομαδική μάθηση / ανταλλαγή γνώσεων