Sedan datorkommunikationens begynnelse har vi haft en förkärlek till request/reply som integrationsmönster. Från början var det RPC, sedan kom CORBA, DCOM, SOAP Web Services och REST. Alla med fokus mot en server som tillhandahåller en tjänst och en klient som frågar och får svar. Många gånger har vi verkligen ansträngt oss för att jobba efter just detta mönster, t.ex. genom att bygga upp en lokal cache för att inte behöva överbelasta servern med frågor. Visst är det ett väldigt användbart mönster, men det har blivit så slentrianmässigt sätt att realisera på att man nästan glömt bort att det finns en annan modell – nämligen publish/subscribe.
Själva namnet publish/subscribe beskriver egentligen mönstret väldigt konkret. Som avsändare av information publicerar man meddelanden och som mottagre av information prenumererar man och blir notifierad när det finns information att tillgå (d.v.s. ”push” i stället för ”pull”). Det enklaste och vanligaste sättet att strukturera meddelanden är genom så kallade ”topics”, eller ämnen. Publicering sker med ett visst ämne och som prenumerant prenumererar jag också på ett visst ämne.
I integrationssammanhang pratar man ofta om lös koppling som en dygd, och publish/subscribe har per definition en lösare koppling än request/reply. Som producent har jag ingen aning om vem som konsumerar mina meddelanden, och som konsument tar jag emot information utan att behöva känna till detaljer om vem som producerat den. Detta innebär t.ex. att man kan lägga till både nya producenter och nya konsumenter utan att påverka tidigare uppsatta parter.
Den extra infrastruktur man använder sig av för att erbjuda publish/subscribe brukar skötas genom en så kallad message broker. Denna erbjuder som regel garanterad leverans och dirigering av meddelanden, vilket gör att man kan fokusera på informationsutbytet snarare än att lägga energi på robust överföring av själva informationen.
Jag har själv arbetat mycket inom retail – och här finns det goda exempel på hur publish/subscribe är ett mycket mer passande mönster än request/reply. Antag först följande scenario: En butikskedja med hundratals butiker och tusentals kassaplatser arbetar med central bokföring. Det betyder att vartenda försäljningskvitto ska skickas löpande in till en central huvudbok. Inom all konsumenthandel är det också fullständigt otänkbart att inte kunna ta betalt – om nätverket går ned ska åtminstone försäljningen rulla på som vanligt.
Det hela blir ännu mer intressant när man inser att kvitton används till så mycket mer än bokföring. Exempelvis sker nedräkning av lagersaldo som en direkt konsekvens av försäljning. För att hålla reda på lagersaldo behöver man bara lägga till lagerhanteringssystemet som prenumerant på kvittoflödet och räkna ned lagersaldo per butik och såld vara utifrån kvittotransaktionerna
När man har en central master för lagersaldo, vilket är trenden för kedjor inom detaljhandel, betyder det att man också behöver läsa lagersaldot från den centrala källan, både för sin egen, men ofta också för andra butiker i kedjan. Här skulle man absolut kunna tänka sig att kassan frågar den centrala funktionen varje gång man är i behov av att veta ett lagersaldo, men när man pratar om flera tusen kassor i en kedja som var och en frågar efter lagersaldo kan det snabbt medföra tiotusentals lagersaldofrågor per minut. Därför är det vettigt att lösa även lagersaldo med ett publish/subscribe-mönster.
De lokala kassorna prenumererar på lagersaldoförändringar, och den centrala miljön behöver enbart publicera lagerrörelserna när de inträffar.
På samma sätt är det sedan väldigt enkelt att lägga till en e-handel till lösningen – alla butikers lagersaldo kan automatiskt publiceras on-line, enbart genom att man lägger till e-handelssystemet som prenumerant på lagerrörelsemeddelanden. Något som är nästan ännu elegantare är att vi automatiskt försäkrat det centrala lagerhanteringssystemet från att sänkas genom trafikanstorming från internet mot e-handeln.
Syftet med detta inlägg är att uppmuntra till att fundera en extra gång innan man slentrianmässigt väljer request/reply som standardsvar på nästa integrationsutmaning.
Det finns också ett asynkront beteende i hela upplägget som beskrivits. Asynkront är alltid lite svårare att ta till sig, men jag tycker mig också se att modern utveckling går mer och mer mot asynkrona mönster, så jag hyser gott hopp om framtiden.
Och till sist – frågar du mig om vilken message broker som man ska använda rekommenderar jag RabbitMQ – snabb, robust och tillgänglig både som open source och i kommersiell förpackning.