Ga direct naar de inhoud
DedicatedPHP Contact

Prioriteiten in PHP-queues zonder urgente taken te blokkeren

Ontwerp prioriteiten in PHP-queues om urgente taken te isoleren, capaciteit te beheersen, uithongering te voorkomen en op belastingpieken te reageren.

Redactioneel diagram van PHP-queues, gescheiden op prioriteit, met werkprocessen voor kritieke, interactieve en bulktaken

Een asynchrone queue voorkomt dat een webverzoek wacht totdat kostbare taken zijn voltooid, maar lost de concurrentie tussen taken niet vanzelf op. Het probleem ontstaat wanneer een import, een herverwerking of een campagne duizenden berichten creëert en alle consumenten bezet. Een actie met onmiddellijke impact —een bestelling bevestigen, voorraad reserveren, een account blokkeren of een transactionele melding versturen— komt achter werk te staan dat kan wachten.

Het beheren van prioriteiten in PHP-queues bestaat niet alleen uit het toevoegen van een numeriek veld aan het bericht. Het is een architectuurbeslissing die de bedrijfsstroom moet weerspiegelen, beperkte afhankelijkheden moet beschermen en voorspelbaar gedrag moet behouden wanneer de belasting toeneemt.

Classificeer werk op impact, termijn en kosten

Classificeer werk op impact, termijn en kosten — guía visual de DedicatedPHP

Maak voordat u queues aanmaakt een inventaris van asynchrone taken. Identificeer voor elke taak wie deze start, welke afhankelijkheid deze gebruikt, hoelang deze doorgaans duurt, welke bedrijfstermijn deze heeft en wat er gebeurt als deze vertraging oploopt. Urgentie staat niet noodzakelijk gelijk aan belang: een financiële afstemming kan zeer belangrijk zijn, maar enkele uren wachten verdragen; een betalingsvalidatie kan snel antwoord vereisen, ook al is de uitvoering ervan kort.

Een nuttige classificatie omvat doorgaans vier serviceklassen:

  • Kritiek: acties die geld, beveiliging, consistentie of onmiddellijke verplichtingen beschermen. Ze moeten een zeer lage doelwachttijd en gereserveerde capaciteit hebben.
  • Interactief: werk dat door een persoon wordt gestart of nodig is om een ervaring dicht bij realtime te voltooien, zoals het genereren van een document dat vanuit de applicatie wordt aangevraagd.
  • Uitgesteld: noodzakelijke taken, maar zonder onmiddellijke termijn, zoals periodieke synchronisaties, samenvattingen of indexupdates.
  • Bulk: imports, migraties, herindexeringen, campagnes en herverwerkingen. Hun volume of kosten vereisen dat hun tempo wordt beperkt, ook wanneer er geen andere belasting is.

Leg ook de kosten per taak vast. Een bericht dat een API met een beperkt quotum aanroept, een intensieve query uitvoert of een groot bestand verwerkt, mag niet op dezelfde manier concurreren als een korte lokale update. De serviceklasse moet de termijn en het type druk uitdrukken dat de taak op het systeem uitoefent.

Scheid queues wanneer u echte isolatie nodig hebt

Eén queue met prioriteiten kan volstaan als taken homogeen worden uitgevoerd, dezelfde afhankelijkheden gebruiken en het transport betrouwbare prioriteit biedt. De ophaalvolgorde garandeert echter op zichzelf niet dat er capaciteit beschikbaar is: een bulktaak die al wordt uitgevoerd, blijft een werkproces, een verbinding of een extern quotum bezetten.

Scheid queues wanneer een van deze grenzen bestaat:

  • Kritieke en bulktaken hebben duidelijk verschillende wachtdoelen.
  • Een type taak maakt gebruik van een kwetsbare afhankelijkheid of een afhankelijkheid met limieten voor aanvraagfrequentie, zoals een API voor betalingen, e-mail of ERP.
  • De duur loopt sterk uiteen en lange taken houden processen te lang vast.
  • Onafhankelijke controle van uitrol, pauzeren, nieuwe pogingen of opschalen is vereist.
  • Een fout of afwijkende invoer uit één stroom mag een andere stroom niet aantasten.

In een PHP-applicatie is het meest leesbare patroon doorgaans berichten naar expliciete queues te routeren, bijvoorbeeld critical, interactive, deferred en bulk. De berichtencomponent kan Symfony Messenger, Laravel Queues of een eigen integratie met de gekozen broker zijn; het principe is niet afhankelijk van het framework. Prioriteit binnen een queue kan deze scheiding aanvullen om vergelijkbare taken te ordenen, maar niet de isolatie tussen incompatibele klassen vervangen.

Definieer gereserveerde capaciteit en maximale gelijktijdigheid

Wijs consumenten per klasse toe en stel zowel operationele minima als maxima in. De kritieke queue heeft capaciteit nodig die niet door imports kan worden opgeslokt. De bulkqueue moet daarentegen een maximum aan gelijktijdige verwerking hebben om database, CPU, opslag of externe providers niet te overbelasten.

Vermijd het configureren van alle werkprocessen om uit alle queues te lezen met absolute voorkeur voor de kritieke queue. Die aanpak kan capaciteit onbenut laten als gereserveerde consumenten geen andere taken kunnen oppakken, of uithongering veroorzaken als ze dat wel zonder regels kunnen doen. Een praktisch alternatief is een combinatie van:

  • Toegewijde werkprocessen voor kritiek en interactief werk.
  • Gedeelde werkprocessen die uitgesteld werk en bulkwerk volgens quota afhandelen.
  • Limieten per type afhankelijkheid, niet alleen per totaal aantal processen.
  • Opschalen op basis van queuediepte en de leeftijd van berichten, niet uitsluitend op CPU-gebruik.

Het juiste aantal is niet universeel. Het moet uitgaan van de gelijktijdigheid die de database en API's tolereren, de waargenomen duur en het wachtdoel van elke klasse.

Voorkom uithongering en pas backpressure toe

Voorrang geven aan urgente zaken betekent niet dat uitgesteld werk nooit moet worden voltooid. Als er altijd kritieke berichten zijn, kan een strikt prioriteitsbeleid uithongering veroorzaken: taken van een lager niveau verouderen onbeperkt. Stel een meetbare eerlijkheidsregel vast, zoals het verwerken van een aantal uitgestelde berichten na een beperkt aantal kritieke berichten, of het reserveren van een klein deel van de capaciteit voor niet-urgent werk.

De regel moet de limieten van afhankelijkheden respecteren. Als kritisch werk en bulkwerk naar dezelfde tabel schrijven met kostbare vergrendelingen, kan het parallel uitvoeren van beide de latentie verslechteren. In dat geval moet het quotum op de gedeelde hulpbron worden toegepast of is het beter de taak in kleinere batches te herontwerpen.

Backpressure ontstaat wanneer er meer werk binnenkomt dan kan worden voltooid. Dit wordt niet opgelost door onbeperkt werkprocessen toe te voegen. Definieer hoe u reageert:

  • Beperk de omvang, frequentie of gelijktijdigheid van imports bij de bron.
  • Splits batches op in hervatbare eenheden en bepaal hoeveel er tegelijk worden gepubliceerd.
  • Stel uitgesteld werk volgens een expliciete planning uit wanneer de queue of een afhankelijkheid een drempel overschrijdt.
  • Respecteer reacties op limieten voor aanvraagfrequentie met pauzes en uitgestelde nieuwe pogingen, in plaats van onmiddellijke nieuwe pogingen.
  • Communiceer aan het product wanneer een bewerking voor verwerking is geaccepteerd en wanneer deze werkelijk is voltooid.

Het is belangrijk acceptatie van uitvoering te onderscheiden: terugmelden dat een import is ontvangen, betekent niet dat deze onmiddellijk kan starten. Die transparantie voorkomt dat een technische wijziging wordt geïnterpreteerd als een belofte van onmiddellijke beschikbaarheid.

Beheer nieuwe pogingen, traagheid en idempotentie

Nieuwe pogingen verbruiken capaciteit en kunnen onbedoeld een prioritaire belasting worden. Classificeer fouten als tijdelijk of permanent. Een tijdelijke netwerkonderbreking kan een nieuwe poging met toenemende wachttijd en temporele spreiding rechtvaardigen; ongeldige invoergegevens, een niet-bestaande hulpbron of ingetrokken inloggegevens moeten naar een beoordelingsproces gaan, niet eindeloos worden herhaald.

Stel een maximale uitvoeringstijd per type taak in. Een trage taak mag een werkproces niet onbeperkt vasthouden. Als de taak kan worden opgesplitst, verwerk dan pagina's, bestanden of segmenten in onafhankelijke berichten die voortgang vastleggen. Zo niet, gebruik dan strikte limieten, veilige annulering en een procedure om uitgeputte taken te beoordelen.

Prioriteit verhoogt het risico op herhaalde effecten wanneer een producent een bericht opnieuw verstuurt of een consument faalt nadat deze een externe API heeft aangeroepen. Ontwerp idempotente berichtverwerkers: gebruik een stabiele bewerkingssleutel, persisteer de status van de transitie en zorg dat tweemaal verwerken hetzelfde bedrijfseffect heeft als eenmaal verwerken. Deduplicatie door de broker kan duplicaten verminderen, maar vervangt idempotentie in de applicatie noch in externe integraties.

Observeer de wachttijd, niet alleen de queuediepte

Een korte queue kan een probleem verbergen als de oudste berichten te lang wachten of als consumenten voortdurend falen. Meet per serviceklasse de leeftijd van het oudste bericht, de tijd vanaf publicatie tot start, de uitvoeringsduur, het percentage fouten, nieuwe pogingen en taken die ter beoordeling zijn doorgestuurd.

Vul deze meetwaarden aan met actieve gelijktijdigheid, diepte, instroom- en uitstroomsnelheid, verbindingsgebruik, responstijden van afhankelijkheden en ontvangen limieten voor aanvraagfrequentie. De nuttigste signalen zijn: de kritieke wachttijd overschrijdt haar doel, de bulkqueue groeit terwijl het quotum beperkt is, nieuwe pogingen domineren het verkeer of gereserveerde capaciteit blijft ongebruikt tijdens pieken in een andere klasse.

Configureer waarschuwingen op trends en servicedoelstellingen, niet alleen op een vast aantal berichten. Duizend berichten kunnen normaal zijn bij een import; tien kunnen ernstig zijn als het bestelbevestigingen betreft die al enkele minuten wachten.

Voorbeeld van gedeelde stroom en implementatielijst

Voorbeeld van gedeelde stroom en implementatielijst — guía visual de DedicatedPHP

Stel u een platform voor dat urgente bestellingen, meldingen en een massale catalogusimport verwerkt. Bestellingen worden naar critical gerouteerd; transactionele meldingen naar interactive; en de import wordt opgesplitst in pagina's die naar bulk worden verstuurd. De werkprocessen voor bestellingen hebben gereserveerde capaciteit. De import heeft beperkte gelijktijdigheid en verlaagt zijn tempo als de databaselatentie toeneemt. De meldingen respecteren het quotum van de provider, met uitgestelde nieuwe pogingen. Als een proces wordt herhaald, voorkomt de bewerkingssleutel dat twee reserveringen worden gemaakt of twee statuswijzigingen worden verstuurd.

Om dit model in een bestaande applicatie in te voeren:

  1. Inventariseer de berichtverwerkers en wijs een serviceklasse toe op basis van termijn, impact en afhankelijkheid.
  2. Meet duur, wachttijd en fouten voordat u de routering wijzigt.
  3. Scheid eerst de kritieke stromen van de bulkstromen en reserveer minimale capaciteit.
  4. Definieer limieten voor gelijktijdigheid per afhankelijkheid en beleid voor backpressure.
  5. Maak bedrijfseffecten idempotent en beperk nieuwe pogingen en uitvoeringstijden.
  6. Test belastingpieken, uitval van providers en massale invoer voordat u de nieuwe verdeling activeert.
  7. Herzie quota en klassen periodiek: een prioriteit is bedrijfsbeleid dat met het product verandert.

Het beoogde resultaat is niet dat alles prioriteit heeft, maar dat elke taak capaciteit en een termijn krijgt die coherent zijn, zonder een operatie met hoog volume in een blokkade voor de rest van het bedrijf te veranderen.

Wil je deze ideeën toepassen op je project?Laten we uw PHP-platform bespreken.
Bekijk gerelateerde service