Επιτηρητές OTP

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

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

Πίνακας περιεχομένων

Ρύθμιση

Η μαγεία των Επιτηρητών είναι στη συνάρτηση Supervisor.start_link/2. Επιπρόσθετα με την εκκίνηση του επιτηρητή και των παιδιών, μας επιτρέπει να ορίσουμε τη στρατηγική που χρησιμοποιεί ο επιτηρητής για τη διαχείριση των διεργασιών παιδιών.

Οι διεργασίες παιδιά ορίζονται με τη χρήση μιας λίστας και της συνάρτησης worker/3 που εισάγουμε από την ενότητα Supervisor.Spec. Η συνάρτηση worker/3 δέχεται μια ενότητα, ορίσματα, και ένα σύνολο επιλογών. Υπόγεια, η worker/3 καλεί τη start_link/3 με τα ορίσματά μας κατά την αρχικοποίηση.

Ας αρχίσουμε χρησιμοποιώντας την ενότητα SimpleQueue από το μάθημα Συγχρονισμός OTP:

import Supervisor.Spec

children = [
  worker(SimpleQueue, [], name: SimpleQueue)
]

{:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one)

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

Στρατηγικές

Αυτή τη στιγμή οι επιτηρητές μας έχουν διαθέσιμες τέσσερις διαφορετικές στρατηγικές επανεκκίνησης:

  • :one_for_one - Επανεκκίνηση μόνο της αποτυχημένης διεργασίας παιδί.

  • :one_for_all - Επανεκκίνηση όλων των διεργασιών παιδί σε περίπτωση αποτυχίας.

  • :rest_for_one - Επανεκκίνηση της αποτυχημένης διεργασίας και κάθε διεργασίας που ξεκίνησε μετά από αυτή.

  • :simple_one_for_one - Καλύτερη για δυναμικά προσαρτημένα παιδιά. Ο επιτηρητής πρέπει να περιέχει μόνο ένα παιδί, άλλα αυτό το παιδί μπορεί να κληθεί πολλές φορές. Η στατηγική αυτή είναι σκόπιμο να χρησιμοποιείται όταν χρειάζεστε να εκκινείτε και να σταματάτε δυναμικά τα επιτηρούμενα παιδιά.

Τιμές Επανεκκίνησης

Υπάρχουν διάφορες προσεγγίσεις για το χειρισμό κρασαρισμάτων διεργασιών παιδιών.

  • :permanent - Η διεργασία παιδί πάντα επανεκκινείται.

  • :temporary - Η διεργασία παιδί δεν επανεκκινείται ποτέ.

  • :transient - Η διεργασία παιδί επανεκκινείται μόνο αν τερματιστεί απρόβλεπτα.

Δεν είναι μια απαιτούμενη επιλογή, εξ’ ορισμού είναι :permanent.

Ενσωμάτωση

Επιπρόσθετα στις διεργασίες εργάτες, μπορούμε να επιτηρήσουμε επιτηρητές για να δημιουργήσουμε ένα δέντρο επιτήρησης. Η μόνη διαφορά σε εμάς είναι η εναλλαγή της supervisor/3 με την worker/3:

import Supervisor.Spec

children = [
  supervisor(ExampleApp.ConnectionSupervisor, [[name: ExampleApp.ConnectionSupervisor]]),
  worker(SimpleQueue, [[], [name: SimpleQueue]])
]

{:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one)

Επιτηρητής Εργασίας

Οι εργασίες έχουν το δικό τους εξειδικευμένο Επιτηρητή, τον Task.Supervisor. Σχεδιασμένος για δυναμικά δημιουργημένες εργασίες, ο επιτηρητής χρησιμοποιεί την :simple_one_for_one.

Εγκατάσταση

Η συμπερίληψη του Task.Supervisor δεν έχει καμμία διαφορά από τους άλλους επιτηρητές:

import Supervisor.Spec

children = [
  supervisor(Task.Supervisor, [[name: ExampleApp.TaskSupervisor]])
]

{:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one)

Επιτηρούμενες Εργασίες

Με τον επιτηρητή να έχει ξεκινήσει, μπορούμε να χρησιμοποιήσουμε τη συνάρτηση start_child/2 για να δημιουργήσουμε μια επιτηρούμενη εργασία:

{:ok, pid} = Task.Supervisor.start_child(ExampleApp.TaskSupervisor, fn -> background_work end)

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