Letar du efter ett lämpligt kösystem?
Söker du ett nytt eller kanske ett mer effektivt system för köhantering? Då har du kommit rätt! Här presenteras all information du kan tänkas behöva.
Kösystem är en underskattad resurs när det kommer till backend-utveckling. Det är kanske en av de bäst bevarade hemligheterna.
Utan att överdriva, kan man påstå att en junior backend-utvecklare tar steget till mellannivå när hen lärt sig att implementera köer i systemet. Köer förbättrar kundupplevelsen (vi ska se hur), minskar komplexiteten och bidrar till högre tillförlitlighet i systemet.
Visserligen, för simpla webbapplikationer med minimal trafik eller enklare webbplatser kan köer kännas som overkill, eller till och med vara omöjliga att installera om du använder en vanlig delad hostingmiljö. Men för mer avancerade applikationer är kösystem en stor fördel och för omfattande system är de rent av nödvändiga.
Innan vi går vidare, en reservation: om du redan känner dig trygg med kösystem och mest är ute efter att jämföra olika alternativ, kan de inledande avsnitten kännas lite tröga. Då kan du med fördel hoppa framåt. De första avsnitten är främst riktade till dig som kanske bara har en vag uppfattning om vad kösystem är eller bara hört talas om det i förbigående.
Vad är ett kösystem?
Låt oss först klargöra vad en kö faktiskt är.
Inom datavetenskap är en kö en datastruktur som efterliknar de köer vi ser i vardagen. Om du exempelvis ska köpa en biljett, ställer du dig i slutet av kön, medan personen längst fram får sin biljett först. Detta är principen ”först in, först ut”. Inom programmering kan vi skapa program som lagrar data på samma sätt, i en kö och bearbetar dem i den ordning de anlände.
Viktigt att komma ihåg är att kön i sig inte bearbetar data. Den fungerar som en tillfällig lagringsplats där uppgifter väntar på att hämtas och hanteras av något annat. Om detta känns abstrakt, oroa dig inte. Det är ett abstrakt koncept, men vi ska titta på konkreta exempel i nästa avsnitt.
Varför behövs kösystem?
Utan att göra en alltför lång utläggning, kan man säga att det primära behovet av kösystem bottnar i bakgrundsbearbetning, parallell körning och återhämtning vid fel. Vi ska se på dessa med några exempel:
Bakgrundsbearbetning
Tänk dig att du driver en e-handelskampanj där tid är avgörande. Din applikation är programmerad så att ett bekräftelsemail skickas precis innan kunden genomför betalningen och omdirigeras till en ”tack”-sida. Om mailservern inte svarar, kommer webbsidan inte att kunna ladda, vilket försämrar användarupplevelsen.
Föreställ dig hur många supportärenden du skulle få! I det här fallet är det bättre att lägga e-postuppgiften i en kö och visa kunden tack-sidan direkt.
Parallell körning
Många utvecklare, särskilt de som jobbar med mindre applikationer med lägre trafik, använder ofta cron-jobb för bakgrundsbearbetning. Det fungerar bra tills mängden inmatning blir för stor. Anta exempelvis att du har ett cron-jobb som sammanställer analysrapporter och mailar ut dem till användare, och att ditt system klarar 100 rapporter per minut.
När applikationen växer och får mer än 100 förfrågningar per minut, kommer den efter ett tag inte kunna slutföra alla jobb.
Med ett kösystem kan man undvika det problemet genom att starta flera arbetare som parallellt kan plocka upp jobb (med 100 rapporter i varje) och slutföra uppgifterna mycket snabbare.
Återhämtning vid fel
Som webbutvecklare tänker vi sällan på fel. Vi utgår från att servrarna och de API:er vi använder alltid är online. Men verkligheten ser annorlunda ut. Nätverksavbrott är vanliga och API:er vi litar på kan krascha på grund av infrastrukturproblem (innan du säger ”inte jag!”, kom ihåg det stora Amazon S3-avbrottet). Om vi återgår till rapportgenereringsexemplet, vad händer om en del av rapporten kräver anslutning till ett betalnings-API och den anslutningen går ner i två minuter? Vad händer med de 200 rapporter som misslyckades?
Kösystem innebär dock kostnader. Inlärningskurvan är brant när man ger sig in i ett nytt område. Komplexiteten i applikationen ökar och köade jobb kan inte alltid kontrolleras exakt. Trots detta finns det situationer där det är omöjligt att bygga en applikation utan köer.
Med detta sagt, låt oss titta på några populära alternativ för köhantering som finns idag.
Redis
Redis är känt som ett nyckel-värdelager som lagrar, uppdaterar och hämtar datasträngar utan kännedom om datastrukturen. Även om det kan ha varit fallet tidigare, har Redis idag effektiva datastrukturer som listor, sorterade uppsättningar och till och med ett Pub-Sub-system, vilket gör det väl lämpat för köimplementeringar.
Fördelarna med Redis är:
- Helt i minnet-databas, vilket ger snabbare läsning/skrivning.
- Mycket effektivt: Kan enkelt hantera mer än 100 000 läs-/skrivoperationer per sekund.
- Flexibelt system för beständighet. Du kan välja maximal prestanda med risken för dataförlust vid fel, eller ett konservativt läge med högre datakonsistens men lägre prestanda.
- Stöd för kluster direkt.
Observera att Redis inte har några abstraktioner för meddelanden, köer eller återställning, så du behöver antingen använda ett bibliotek eller bygga ett eget system. Ett exempel är att Redis är standardköbackend i Laravel PHP-ramverket, där en schemaläggare har implementerats av ramverksutvecklarna.
Att lära sig Redis är enkelt.
RabbitMQ
Det finns några subtila skillnader mellan Redis och RabbitMQ. Låt oss klargöra dem först.
Först och främst har RabbitMQ en mer specialiserad och väldefinierad roll, utformad för att hantera meddelanden. Med andra ord är dess specialitet att fungera som en mellanhand mellan två system, vilket inte är fallet för Redis som fungerar som en databas. Därför erbjuder RabbitMQ ytterligare funktioner som saknas i Redis: meddelanderoutning, återförsök, lastfördelning etc.
Om man tänker efter kan uppgiftsköer också ses som ett meddelandesystem, där schemaläggaren, arbetarna och de som skickar in jobb ses som enheter som deltar i meddelandeöverföringen.
RabbitMQ har följande fördelar:
- Bättre abstraktioner för att skicka meddelanden, vilket minskar arbetet på applikationsnivå om meddelandeöverföring är det du behöver.
- Tåligare mot strömavbrott och avbrott (än Redis, åtminstone som standard).
- Stöd för kluster och federation för distribuerade system.
- Användbara verktyg för att hantera och övervaka din installation.
- Stöd för i princip alla programmeringsspråk av betydelse.
- Enkel att implementera med valfritt verktyg (Docker, Chef, Puppet, etc.).
När ska man välja RabbitMQ? Det är ett utmärkt val om du vet att du behöver asynkron meddelandeöverföring, men inte vill hantera den höga komplexiteten hos andra köalternativ på den här listan (se nedan).
ActiveMQ
Om du är verksam inom företagsområdet (eller bygger en distribuerad och storskalig applikation) och inte vill återuppfinna hjulet (med misstag som följd), är ActiveMQ värt att undersöka.
Detta utmärker ActiveMQ:
- Implementerat i Java, med smidig Java-integration (följer JMS-standarden).
- Stöd för flera protokoll: AMQP, MQTT, STOMP, OpenWire etc.
- Hanterar säkerhet, routing, meddelandeålder, analyser etc. direkt.
- Inbyggt stöd för populära distribuerade meddelandemönster, vilket sparar tid och kostsamma fel.
ActiveMQ är inte begränsat till Java. Det finns klienter för Python, C/C++, Node, .Net och andra miljöer, så framtida problem bör inte uppstå. ActiveMQ bygger på öppna standarder, så att bygga egna klienter bör vara enkelt.
Men tänk på att ActiveMQ bara är en mäklare, inte en backend. Du behöver fortfarande använda en av de stödda backends för att lagra meddelanden. Jag har tagit med det här eftersom det inte är kopplat till ett visst programmeringsspråk (som andra populära lösningar som Celery, Sidekiq etc.).
Amazon MQ
Amazon MQ förtjänar ett omnämnande här. Om du anser att ActiveMQ är en idealisk lösning, men inte vill bygga och underhålla infrastrukturen själv, erbjuder Amazon MQ en hanterad tjänst för det ändamålet. Den stöder alla protokoll som ActiveMQ – det finns ingen skillnad i funktion – eftersom den använder ActiveMQ under ytan.
Fördelen är att det är en hanterad tjänst, så du slipper oroa dig för annat än att använda den. Det är ännu mer relevant för installationer som körs på AWS, eftersom du kan dra nytta av andra tjänster direkt från din installation (t.ex. snabbare dataöverföringar).
Amazon SQS
Vi kan väl inte förvänta oss att Amazon ska vara passiva när det gäller kritisk infrastruktur? 🙂
Därför har vi Amazon SQS, en helt värdbaserad, enkel kötjänst från AWS. Återigen är det viktigt att notera subtila skillnader: SQS har inte konceptet att skicka meddelanden. Precis som Redis är det en enkel backend för att ta emot och distribuera jobb i köer.
När är det lämpligt att använda Amazon SQS? Här är några anledningar:
- Du är ett fan av AWS och vill inte använda något annat (det finns många sådana och det är helt okej).
- Du behöver en serverlös lösning med garanterad tillförlitlighet och att inga jobb går förlorade.
- Du vill inte bygga ett kluster och övervaka det själv. Eller ännu värre, bygga övervakningsverktyg när du kan lägga den tiden på produktiv utveckling.
- Du har redan investerat mycket i AWS-plattformen och att hålla sig till den är ett bra affärsbeslut.
- Du vill ha ett fokuserat, enkelt kösystem utan extra funktioner som är relaterade till meddelandeöverföring, protokoll etc.
Sammantaget är Amazon SQS ett bra val för alla som vill implementera jobbköer i sitt system utan att behöva oroa sig för att installera/övervaka saker själva.
Beanstalkd
Beanstalkd har funnits länge och är en beprövad, snabb och enkel backend för jobbköer. Det finns vissa egenskaper som gör att Beanstalkd skiljer sig från Redis:
- Det är uteslutande ett jobbkösystem och inget annat. Du skickar jobb till det, som senare hämtas av arbetare. Så om din applikation har ett behov av att skicka meddelanden, är Beanstalkd inte ett bra alternativ.
- Det finns inga avancerade datastrukturer som uppsättningar, prioritetsköer etc.
- Beanstalkd använder en princip som kallas ”First In, First Out” (FIFO). Det finns inget sätt att ordna jobb efter prioritet.
- Det finns inga alternativ för klustring.
Med detta sagt erbjuder Beanstalkd ett smidigt och snabbt kösystem för enkla projekt som körs på en enda server. För många är det snabbare och stabilare än Redis. Om du har problem med Redis som du inte kan lösa, och dina behov är enkla, är Beanstalkd värt ett försök.
Sammanfattning
Om du har läst så här långt (eller skummat texten 😉) är chansen stor att du är intresserad av kösystem eller behöver ett. Om så är fallet, kommer listan på den här sidan att vara till stor hjälp, om du inte letar efter ett språkspecifikt eller ramverksspecifikt kösystem.
Jag önskar att jag kunde säga att köhantering är enkelt och 100% pålitligt, men så är det inte. Det kan vara komplicerat, och eftersom allt händer i bakgrunden och går väldigt fort, kan fel missas och bli kostsamma. Trots det är köer nödvändiga, och de blir ett kraftfullt vapen (kanske det mest kraftfulla) i din arsenal. Lycka till! 🙂