Διαχείριση πόρων
Το Queuety διαχωρίζει τον έλεγχο πόρων σε τέσσερα βασικά επίπεδα, με προαιρετική προσαρμογή μεγέθους συνόλου επιπλέον.
Το πρώτο επίπεδο περιγράφει πόσο δαπανηρή είναι μία μονάδα εργασίας. Το δεύτερο περιορίζει το πόση κοινόχρηστη επιβάρυνση επιτρέπεται να αναλάβει ταυτόχρονα μία ουρά ή ομάδα παρόχων. Το τρίτο ορίζει πόσους πόρους μπορεί να καταναλώσει μια μεμονωμένη εκτέλεση ροής εργασίας. Το τέταρτο αποφασίζει αν ένας εργαζόμενος πρέπει να ξεκινήσει αμέσως την επόμενη εργασία που ανέλαβε ή να την αναβάλει μέχρι η διεργασία και το κοντέινερ να διαθέτουν επαρκή περιθώρια πόρων.
Αυτά τα επίπεδα συνεργάζονται. Ένας χειριστής μπορεί να δηλώσει ότι ανήκει σε μια κοινόχρηστη ομάδα υψηλού κόστους, μια ουρά μπορεί να δεσμεύει μόνο συγκεκριμένο σταθμισμένο φόρτο για έναν πάροχο, μια ροή εργασίας μπορεί να περιορίζει το μέγεθος του φόρτου που είναι διατεθειμένη να δημιουργήσει και ο εργαζόμενος μπορεί να αρνηθεί να ξεκινήσει περισσότερη εργασία όταν η διεργασία ή το κοντέινερ πλησιάζει ήδη τα όριά του.
Περιγραφή του κόστους μιας μονάδας εργασίας
Οι εργασίες, τα βήματα ροών εργασίας και οι ενέργειες εισόδου κατάστασης μπορούν όλα να δημοσιεύουν τις ίδιες τρεις υποδείξεις πόρων:
concurrency_groupconcurrency_limitcost_units
Τα concurrency_group και concurrency_limit περιγράφουν την κοινόχρηστη επιβάρυνση ενός συστήματος στο οποίο βασίζονται. Αν πολλοί χειριστές καλούν τον ίδιο πάροχο, τον ίδιο λογαριασμό API ή τον ίδιο μισθωτή, μπορούν να χρησιμοποιούν την ίδια ομάδα, ώστε οι εργαζόμενοι να μην ξεκινούν υπερβολικά πολλές κλήσεις ταυτόχρονα.
Το cost_units περιγράφει το σχετικό βάρος. Μια ανανέωση cache και μια μεγάλη κλήση παρόχου μπορεί να είναι αμφότερες «μία εργασία», αλλά δεν πρέπει να συνεισφέρουν εξίσου όταν ένας προϋπολογισμός ροής εργασίας ή ένας κανόνας έγκρισης εργαζομένων κρίνει αν είναι ασφαλές να ξεκινήσει περισσότερη εργασία.
final class CallProviderStep implements \Queuety\Step
{
public function handle( array $state ): array
{
// ...
}
public function config(): array
{
return [
'concurrency_group' => 'providers',
'concurrency_limit' => 3,
'cost_units' => 5,
];
}
}
Η ίδια ιδέα εφαρμόζεται στις εργασίες που μπορούν να αποσταλούν μέσω ιδιοτήτων κλάσης και στις μεμονωμένες αποστολές μέσω των PendingJob::concurrency_group() και PendingJob::cost_units().
Προϋπολογισμός κοινόχρηστων ουρών και ομάδων παρόχων
Η κοινόχρηστη επιβάρυνση δεν αφορά πάντα έναν απλό αριθμό ταυτόχρονων εκτελέσεων. Μερικές φορές, το δαπανηρό στοιχείο είναι το συνδυασμένο βάρος των εργασιών που εκτελούνται ήδη.
Το Queuety το υποστηρίζει μέσω σταθμισμένων προϋπολογισμών ουρών και ομάδων. Οι προϋπολογισμοί ουράς βασίζονται στο όνομα της ουράς. Οι προϋπολογισμοί ομάδας βασίζονται στο concurrency_group, επιτρέποντας σε άσχετους χειριστές να συμμετέχουν στο ίδιο κοινόχρηστο πλαίσιο ορίων.
define( 'QUEUETY_RESOURCE_QUEUE_COST_BUDGETS', [
'providers' => 20,
'exports' => 8,
] );
define( 'QUEUETY_RESOURCE_GROUP_COST_BUDGETS', [
'openai' => 12,
'tenant:acme' => 6,
] );
Όταν ένας εργαζόμενος αναλαμβάνει μια εργασία, εξετάζει τις ενεργές εγγραφές processing που ανήκουν ήδη σε αυτήν την ουρά ή ομάδα. Αν το κόστος των εργασιών που εκτελούνται μαζί με το cost_units της εργασίας που αναλήφθηκε υπερβαίνουν τον καθορισμένο προϋπολογισμό, ο εργαζόμενος αποδεσμεύει την εργασία και δοκιμάζει ξανά αργότερα.
Αυτό σας δίνει έναν διαφορετικό έλεγχο από το concurrency_limit. Ένας πάροχος μπορεί να επιτρέπει τρία ταυτόχρονα αιτήματα, αλλά να δεσμεύει λιγότερες συνολικές μονάδες κόστους για μεγαλύτερα αιτήματα απ' ό,τι για μικρότερα.
Διατηρήστε μια ροή εργασίας μέσα σε όρια
Οι προϋπολογισμοί ροών εργασίας είναι χρήσιμοι όταν το πρόβλημα δεν είναι μία βαριά εργασία, αλλά μια εκτέλεση που συνεχίζει να ανακαλύπτει περισσότερη δουλειά απ' όση προβλέπεται.
Αυτό είναι συνηθισμένο σε συστήματα με πράκτορες. Ένας σχεδιαστής μπορεί να επισκέπτεται ξανά τον ίδιο δαπανηρό κλάδο, να διασπά ένα αίτημα σε υπερβολικά πολλές υποεργασίες ή να ξεκινά συνεχώς θυγατρικές ροές εργασίας, παραμένοντας τυπικά εντός ενός συνηθισμένου μοντέλου επαναλήψεων.
Το Queuety παρέχει όρια σε επίπεδο ροής εργασίας για αυτό:
Queuety::workflow( 'research_run' )
->max_transitions( 20 )
->max_for_each_items( 12 )
->max_state_bytes( 32768 )
->max_cost_units( 40 )
->max_started_workflows( 8 )
->then( PlanResearchStep::class )
->for_each( 'tasks', ExecuteResearchTask::class, 'results' )
->dispatch();
Το max_cost_units() εμποδίζει την εκτέλεση να καταναλώσει περισσότερο σταθμισμένο φόρτο απ' όσο προβλέπεται. Το max_started_workflows() εμποδίζει μια γονική εκτέλεση να μετατραπεί σε απεριόριστο δέντρο θυγατρικών εκτελέσεων ανώτατου επιπέδου. Οι υπόλοιπες δικλίδες εξακολουθούν να έχουν σημασία, επειδή δεν είναι όλες οι ροές εργασίας που ξεφεύγουν εξίσου δαπανηρές.
Η κατάσταση της ροής εργασιών εμφανίζει τα διαμορφωμένα όρια και την τρέχουσα χρήση μέσω του δημόσιου payload budget, ώστε η εκτέλεση να παραμένει ελέγξιμη όσο ισχύουν αυτά τα όρια.
Αφήστε τους workers να αναβάλλουν εργασίες όταν η διεργασία είναι ήδη υπερφορτωμένη
Ακόμη κι όταν οι προϋπολογισμοί μεταδεδομένων και ροής εργασιών έχουν ρυθμιστεί σωστά, η τελική απόφαση ανήκει στη διεργασία worker που πρόκειται να εκτελέσει την εργασία.
Εδώ έρχεται η διαχείριση εισαγωγής με επίγνωση των πόρων. Πριν ξεκινήσει μια εργασία που έχει αναληφθεί, το Queuety μπορεί να εξετάσει:
- την κοινόχρηστη ομάδα ταυτόχρονων εργασιών της εργασίας
- τους σταθμισμένους προϋπολογισμούς ουράς και ομάδας παρόχων
- το πρόσφατο ιστορικό διάρκειας και μέγιστης χρήσης μνήμης του χειριστή
- το διαθέσιμο περιθώριο μνήμης του τρέχοντος worker
- το διαθέσιμο περιθώριο μνήμης του τρέχοντος container ή host
- το χρονικό περιθώριο που απομένει για εκτελέσεις τύπου one-shot
Αν ο worker πλησιάζει ήδη υπερβολικά το διαμορφωμένο όριό του, το Queuety αποδεσμεύει την εργασία αντί να ξεκινήσει μια εργασία που είναι απίθανο να ολοκληρωθεί ομαλά.
Αυτό είναι σκόπιμα συντηρητικό. Δεν πρόκειται για πλήρη scheduler συστάδας. Είναι ένα επίπεδο προστασίας που βοηθά έναν απασχολημένο worker να αποφύγει την υπερδέσμευση της διεργασίας στην οποία εκτελείται και, όταν υπάρχουν διαθέσιμα δεδομένα τηλεμετρίας μνήμης, του container ή του host που την περιβάλλει.
Η υποστήριξη για container ή host είναι προαιρετική. Όταν είναι ενεργοποιημένο το QUEUETY_RESOURCE_SYSTEM_MEMORY_AWARENESS, το Queuety προσπαθεί πρώτα να διαβάσει δεδομένα μνήμης cgroup και, σε host Linux, χρησιμοποιεί το /proc/meminfo ως εφεδρική επιλογή. Αν δεν υπάρχει αξιόπιστο στιγμιότυπο σε επίπεδο συστήματος, ο worker συνεχίζει να χρησιμοποιεί τους ελέγχους τοπικά στη διεργασία.
Κλιμακώστε τις δεξαμενές worker χωρίς να αγνοείτε τη χωρητικότητα
Οι δεξαμενές worker σταθερού μεγέθους είναι εύκολες στην κατανόηση, αλλά σας αναγκάζουν να επιλέξετε έναν αριθμό τόσο για τις ήσυχες περιόδους όσο και για τις αιχμές.
Οι προσαρμοστικές δεξαμενές σάς επιτρέπουν να ορίσετε ένα κατώτατο και ένα ανώτατο όριο:
wp queuety work --queue=providers --min-workers=2 --max-workers=6
Η γονική διεργασία διατηρεί ενεργά τουλάχιστον τον ελάχιστο αριθμό θυγατρικών διεργασιών, αυξάνεται προς το μέγιστο όταν αυξάνονται οι εργασίες που μπορούν να αναληφθούν και μειώνεται όταν η ουρά παραμείνει ήσυχη για το διαμορφωμένο χρονικό περιθώριο αδράνειας.
Η αύξηση μεγέθους εξακολουθεί να λαμβάνει υπόψη τη διαθέσιμη χωρητικότητα. Αν είναι ενεργοποιημένη η επίγνωση μνήμης συστήματος και η γονική διεργασία δεν βλέπει αρκετή διαθέσιμη μνήμη για το πλήρες αποτύπωμα ενός ακόμη worker, διατηρεί το τρέχον μέγεθος της δεξαμενής αντί να εκκινήσει περισσότερες θυγατρικές διεργασίες.
Ένας ρεαλιστικός τρόπος συνδυασμού των επιπέδων
Φανταστείτε μια ροή εργασιών έρευνας που σχεδιάζει κλήσεις σε παρόχους, εκκινεί εξειδικευμένες ροές εργασιών και στη συνέχεια συνθέτει το αποτέλεσμα.
Το βήμα που επικοινωνεί με τον πάροχο μπορεί να δημοσιεύει το cost_units και ένα κοινόχρηστο concurrency_group, ώστε πολλοί worker να μην κατακλύζουν τον ίδιο πάροχο μοντέλου. Η ουρά μπορεί να δεσμεύει σταθμισμένο προϋπολογισμό για την κίνηση προς αυτόν τον πάροχο. Η γονική ροή εργασιών μπορεί να θέτει όριο στα max_cost_units() και max_started_workflows(), ώστε ένα πρόγραμμα σχεδιασμού να μην μπορεί να επεκτείνει την εκτέλεση επ' αόριστον. Έπειτα, ο worker μπορεί και πάλι να αναβάλει μια κλήση παρόχου που μόλις ανέλαβε, αν τα πρόσφατα δεδομένα μέγιστης χρήσης μνήμης δείχνουν ότι η διεργασία ή το container πλησιάζει υπερβολικά το όριό του.
Αυτό σας δίνει τέσσερις ξεχωριστούς ελέγχους:
- περιγράψτε το βάρος της εργασίας
- δεσμεύστε κοινόχρηστη χωρητικότητα ουράς ή παρόχου
- θέστε όριο σε όσα επιτρέπεται να δημιουργήσει μία εκτέλεση
- αποτρέψτε έναν απασχολημένο worker από το να ξεκινήσει περισσότερες εργασίες από όσες πρέπει
Πού βρίσκονται τα αναλυτικά API
Αυτή η σελίδα είναι η εννοιολογική επισκόπηση.
Για τις συγκεκριμένες επιλογές:
- Workers καλύπτει τη συμπεριφορά εισαγωγής και τις σταθερές χρόνου εκτέλεσης
- CLI καλύπτει τις εντολές για δεξαμενές worker σταθερού και προσαρμοστικού μεγέθους
- Προστατευτικά όρια ροής εργασιών καλύπτει τους προϋπολογισμούς ροής εργασιών
- Εργασίες καλύπτει τα μεταδεδομένα εργασιών και χειριστών
- Μηχανές κατάστασης καλύπτει τα μεταδεδομένα πόρων ενεργειών κατάστασης
- API παραθέτει τις ακριβείς μεθόδους και τις μορφές επιστρεφόμενων τιμών