Πώς να κάνετε οποιοδήποτε NodeJS App χωρίς διακομιστή

Ελπίζω να αγαπάτε τον Serverless όσο και εγώ γιατί αυτό είναι ακόμα μια ακόμη θέση σε αυτό το θέμα.

Τώρα, αν μιλάμε για ένα απλό API REST API χωρίς διακομιστή, η ρύθμισή σας είναι αρκετά προφανής στο AWS: Lambda + API Gateway.

Αλλά τι γίνεται με άλλες (μικρο) υπηρεσίες που μπορεί να έχει η backend σας; Ξέρετε, δεν είναι η καλύτερη ιδέα να τοποθετήσετε όλο τον κώδικα αίτησής σας σε μια μοναδική μονολιθική λειτουργία Lambda AWS.

Η πρόκληση

Θέλουμε να αναπτύξουμε εύκολα τις λειτουργικές μονάδες εφαρμογών ως microservices χωρίς διακομιστές, οι οποίοι επίσης πρέπει να επικοινωνούν μεταξύ τους. Κατά προτίμηση, η επικοινωνία μεταξύ των υπηρεσιών πρέπει να ρυθμίζεται από ένα είδος ACL.

Προσπάθεια 1. Gateway API

Αυτή είναι η πρώτη σκέψη που είχα όταν προσπαθούσα να λύσω το πρόβλημα: απλά εκθέστε όλες τις μικροεπιχειρήσεις μέσω του API Gateway. Το πρόβλημα είναι ... Τα δημιουργούμενα API είναι δημόσια.

Γιατί αυτό είναι ένα πρόβλημα; Για παράδειγμα, δεν θέλουμε να έχουμε μια υπηρεσία χρέωσης να εκτίθεται σε ολόκληρο τον κόσμο, ακόμη και αν η πρόσβαση περιορίζεται με κάποιο είδος εξουσιοδότησης.

Λοιπόν, μπορείτε να κάνετε το API ιδιωτικό, αλλά οι πολιτικές ασφάλειας είναι αρκετά περιορισμένες:

Μπορείτε να χρησιμοποιήσετε τις πολιτικές πόρων των API Gateway για να επιτρέψετε την ασφαλή κλήση του API σας:
* χρήστες από έναν συγκεκριμένο λογαριασμό AWS
* καθορισμένες περιοχές διευθύνσεων IP προέλευσης ή μπλοκ CIDR
* συγκεκριμένα εικονικά ιδιωτικά σύννεφα (VPC) ή τελικά σημεία VPC (σε οποιονδήποτε λογαριασμό)

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

Προσπάθεια 2. Lambda

Γιατί δεν θέτουμε απλώς όλες τις μικροεπιχειρήσεις σε μια ξεχωριστή AWS Lambda; Θα λύσει αυτό το πρόβλημα;

Ναι, στην πραγματικότητα θα είναι μια μικροεπεξεργαστή χωρίς διακομιστές και θα μπορείτε να χρησιμοποιήσετε πολιτικές IAM για να συντονίσετε τις προσπελάσεις μεταξύ υπηρεσιών, αλλά ... Δεν είναι εύκολο.

Γνωρίζω ότι είναι απολύτως φυσιολογικό σήμερα να έχουμε μια μικροσκοπική λειτουργία ως μονάδα ανάπτυξης. Και στην περίπτωση που η υπηρεσία σας έχει περισσότερα από ένα τελικά σημεία / μεθόδους / λειτουργίες, θεωρείται εντάξει να την αναπτύξετε ως πολλαπλά Lambdas.

Καταλαβαίνω τα πλεονεκτήματα του, αλλά θυσιάζετε την ευκολία συντήρησης και ανάπτυξης. Επίσης, πραγματικά δεν μου αρέσει μια ιδέα να έχουμε μια υπηρεσία που αναπτύσσεται ως ένα σύνολο λειτουργιών Lambda. Φανταστείτε, πολλές ξεχωριστές λειτουργίες που ασχολούνται με την τιμολόγηση; Δεν είναι πλέον ένα οριοθετημένο πλαίσιο. Παρόλο που υπάρχουν περιπτώσεις όπου μια τέτοια ιδιαιτερότητα μπορεί να είναι χρήσιμη, αλλά είναι μια σπάνια περίπτωση.

Προσπάθεια 3. Λίπος Λάμδα

Μπορούμε πραγματικά να αναπτύξουμε ένα σύνολο τελικών σημείων ως ένα ενιαίο Lambda (χωρίς τη χρήση του API Gateway, φυσικά);

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

Ο τρόπος που θέλω είναι το εξής: κάθε υπηρεσία που μπορεί να αναπτυχθεί πρέπει να είναι ένα απλό απλό παλιό αντικείμενο JS με μεθόδους. Αυτό είναι αρκετά ασήμαντο για να επιτευχθεί προσθέτοντας μερικές γραμμές κώδικα κόλλας μεταξύ του αντικειμένου σας και του AWS Lambda.

Εδώ είναι η εφαρμογή μου: aws-rpc. Αυτή η ενότητα nodejs εκθέτει τη λειτουργία lambdaHandler, όπου μόλις περάσετε ένα αντικείμενο και είναι αυτόματα εκτεθειμένη σε οποιονδήποτε έχει πρόσβαση στο Lambda:

εισαγωγή {lambdaHandler} από το "aws-rpc";
εισαγάγετε {TestServiceImpl} από το "./TestServiceImpl".
// Αυτή είναι η μονάδα ανάπτυξης
// αυτό είναι αυτό που ορίζετε ως λειτουργία χειριστή Lambda
εξαγωγή const χειριστής = lambdaHandler (new TestServiceImpl ());

Τώρα, μπορείτε απλά να αναπτύξετε "χειριστή" ως AWS Lambda. Εδώ μπορείτε να χρησιμοποιήσετε τις μεθόδους του:

εισαγωγή {TestService} από το "./TestService".
const πελάτης = await createClient  ("LambdaName", "test")?
console.log (περιμένετε client.test ());

Σημειώστε ότι για να μπορέσετε να δημιουργήσετε μεθόδους για το αντικείμενο stub του πελάτη, πρέπει να περάσετε όλα τα ονόματα μεθόδων στο createClient, όπως κάναμε στο παράδειγμα.

Αυτό απαιτείται επειδή η JS δεν διαθέτει πληροφορίες χρόνου εκτέλεσης σχετικά με διεπαφές TypeScript. Θα μπορούσα να το εφαρμόσω χρησιμοποιώντας αφηρημένα μαθήματα, αλλά δεν μου αρέσει αυτό το ¯ \ _ (ツ) _ / ¯.

Δώρο! Μπορείτε να το εκτελέσετε όλα τοπικά!

Πιστεύω ότι είναι πολύ σημαντικό να έχετε το τοπικό σας περιβάλλον ανάπτυξης όσο το δυνατόν πιο άνετα. Αυτός είναι ο λόγος για τον οποίο πρόσθεσα επίσης την ικανότητα να τρέχω τοπικά την υπηρεσία και τον πελάτη χωρίς να αναπτύξω τίποτα στο AWS (δείτε λειτουργίες runService και createClient). Για παραδείγματα, δείτε την αποθήκη στο GitHub.

Περίληψη

Αυτό είναι πολύ εύκολο να χαθεί στις υπηρεσίες που προσφέρουν οι πάροχοι νέφους και να υπερέχει την υποδομή σας.

Διαλέγω πάντα την πιο απλή και σαφή λύση που μπορώ να σκεφτώ. Επίσης, να θυμάστε πάντα ότι πολλές τεχνικές και πρακτικές μπορούν να επαναχρησιμοποιηθούν από άλλες πλατφόρμες (η ιδέα του λίπους NodeJS Lambda είναι εμπνευσμένη από τα αποκαλούμενα βάζα λίπους από τον κόσμο της Java).

Εάν σας άρεσε αυτό το θέμα, ελέγξτε και αυτά τα εξής:

  • Πρέπει να μάθετε πώς να κάνετε την καλύτερη Αρχιτεκτονική χωρίς διακομιστές
  • Πώς να δημιουργήσετε δωρεάν αγωγό CI / CD χωρίς διακομιστή: 3 εύκολα παραδείγματα
  • Πώς να αντιγράψετε εύκολα το DynamoDB σε διάφορες περιοχές
  • Πώς να κάνετε πολυπεριφερειακή εφαρμογή (και να πληρώσετε μηδέν)
  • Κάντε οποιοδήποτε διακομιστή Java Web App χωρίς διακομιστή

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