Sådan opbygger du en moderne Business Rules Engine, et hurtigt overblik

apr 22, 2021
admin

Dette er et konceptuelt overblik på højt niveau over arkitekturen for en Business Rules Engine. Den ligger over den egentlige kode. Hvis du er ved at bygge en business rules engine – er der stor sandsynlighed for, at du kan finde denne tekst nyttig.

Engang byggede jeg en Business Rules Engine, som muliggjorde forretningsautomatisering for små og mellemstore virksomheder, og som også havde alle muligheder og potentiale til at tjene godt til store virksomheder. Det var en vej fra en almindelig softwareapplikation til en sofistikeret og kompleks løsning, der opfyldte de hårde krav til skalerbarhed, vedligeholdbarhed og udvidelsesmuligheder. Denne tekst vil give et overblik over, hvad Business Rules Engine er, og beskrive en af de moderne tilgange til opbygning af den, som du kan overveje, når du skal opbygge denne type software.

Til at begynde med er det vigtigt at definere grundlæggende begreber. Business rule engines har eksisteret i branchen i ret lang tid i en eller anden form, og der er givet nogle definitioner for stort set alle de udtryk, vi kommer til at bruge. Lad os starte med en “forretningsregel” – der findes en velkendt definition for dette begreb. En “forretningsregel” er således:

En erklæring, der definerer eller begrænser et eller andet aspekt af forretningen. Den har til formål at bekræfte forretningsstrukturen eller at kontrollere eller påvirke forretningens adfærd.

T. Morgan, Business Rules and Information Systems. Boston: Addison-Wesley Publishing, 2002

Businessregler har et meget bredt anvendelsesområde og kan anvendes på alle aspekter af forretningen. F.eks. anvendes reglen “Når en kunde kommer ind, skal du hilse på ham med et varmt smil og et venligt “Hej” af virksomhedens medarbejder, når han møder kunderne. En anden regel kan definere eller begrænse tilgangen til løsning af rutineopgaver for en bestemt rolle i en virksomhed. Med den stadigt stigende popularitet af softwareløsninger som CRM-systemer og med den totale integration af software til en række forskellige forretningsområder er de fleste forretningsprocesser blevet helt eller delvist dataorienterede. Dette har ført til, at forretningsreglerne er blevet softwareorienterede, f.eks. er forretningsreglen “Når en kunde køber noget i vores butik, skal du ringe til ham senere og spørge, om han ønsker at købe andre relaterede varer” blevet ændret til en mere moderne “Når en kunde køber noget i vores onlinebutik, skal du sende ham en e-mail med en liste over andre relaterede varer senere”. I dag beskæftiger mange virksomheder sig mest med data i deres daglige drift. I betragtning af, at de fleste virksomheder af alle størrelser har integreret softwareløsninger i deres forretningsaktiviteter, kan definitionen af begrebet “forretningsregel” defineres mere specifikt ved at tilføje en præcisering (den er med fed skrift) til ovennævnte definition af T. Morgan:

En forretningsregel er et udsagn, der definerer eller begrænser et eller andet aspekt af forretningen. Den har til formål at bekræfte forretningsstrukturen eller at kontrollere eller påvirke forretningens adfærd. Den gemmes som en datakonstruktion i det vedvarende lager og indeholder en atomar pakke af forretningslogik. Den forvaltes og anvendes automatisk i virksomhedens forretningsprocesser via en softwareløsning.

Når begrebet “forretningsregel” er defineret, defineres begrebet “Business Rules Engine Management System” (BRMS) som følger:

BRMS er en softwareløsning til forvaltning (lagring, redigering og sletning osv.) af forretningsregler samt til anvendelse af dem i virksomhedens forretningsprocesser.

Standalone kommercielle BRMS’er kan være ekstremt dyre at købe licensen og integrere dem i virksomhedens it-infrastruktur, og derfor implementerer virksomhederne ofte interne løsninger, når de støder på et behov for at automatisere forretningsprocesser eller andre former for processer.
BRMS’er kan blive en væsentlig og vital del af enhver virksomhed. Nogle gange kan en virksomheds succes afhænge af de forretningsregler, den har, og hvor godt disse forretningsregler forvaltes og anvendes.

Datakonstruktionen for forretningsregler

En forretningsregel kan repræsenteres som en konsekvent serie af atomare kommandoer. Kommandoerne kan omfatte betingede dataanalyser, tidsvente-kommandoer, handlingsudførelseskommandoer osv. Eksemplet med forretningsreglen “Når en kunde køber noget i vores onlinebutik, send ham senere en e-mail med en liste over andre relaterede varer” er et godt og generisk eksempel, og mange andre forretningsregler kan have en meget lignende logisk struktur:

Flowet for regelbehandling startes, når der er foretaget et køb, og der anvendes noget forretningslogik ved at udføre kommandoen “Send køberen en e-mail med relevante varetilbud”. Det kan ske så, at køberen har deaktiveret e-mail-abonnementet. Så skal der tilføjes en yderligere betingelse til forretningsreglen – “hvis køberen har aktiveret e-mail-abonnement”:

Kommandoerne udføres i forlængelse heraf, og der er nu en dataanalysekommando til at kontrollere, om køberen har et aktivt e-mail-abonnement. Hvis det er tilfældet – fortsæt til udførelsen af den næste kommando i forretningsreglen. Og hvis ikke – fortsæt ikke, forretningsreglen betragtes som afsluttet, behandlingsflowet stopper, og de efterfølgende kommandoer udføres ikke.

Køberen kan også have et SMS-abonnement, og hvis det er aktivt, bør der også være en anden kommando – “Send en SMS med tilhørende kampagnetilbud”. Dermed indføres forgrening i forretningsreglens logik:

Reglens grene afvikles uafhængigt af hinanden. Behandlingen af en af grenene kan stoppe ved kommandoen til evaluering af betingelsen, og en anden gren kan behandles frem til slutningen.

UI’et af BRMS-klientapplikationen til repræsentation af en forretningsregel kan implementeres på forskellige måder (enhver form for grafisk repræsentation i form af et træ kan fungere):

Et eksempel på den grafiske repræsentation af forretningsregler

Den grafiske datakonstruktion af forretningsregler er en rettet rodfæstet trægraf (en rettet acyklisk graf, der har et træ som en underliggende urettet graf). Vertices i forretningsregelgrafen er repræsenteret med forskellige former for kommandoer: dataanalysekommandoer, handlingsudførelseskommandoer, tid-vente-kommandoer osv. Alle rettede, rodfæstede ud-træer har en rod – et toppunkt, hvorfra alle kanter peger ud. Hver regel starter således med et særligt punkt (eller rodpunkt i grafteori) – det punkt, som er indgangspunktet for regelbehandlingen.

CRUD-operationer på forretningsregel-datakonstruktionen

Da datakonstruktionen er repræsenteret med et træ med en rettet rod og aldrig nogen anden form for graf, slipper vi for de ulemper, der følger med lagring af generelle grafstrukturer med RDBMS (som f.eks. lagring af hjørner og kanter i forskellige tabeller, hvilket kan resultere i et øget antal opslag for en enkelt regeloprettelse osv.) Og dette er kritisk, fordi det er klart, at under den normale drift af BRMS dataopslag sker meget oftere, end andre operationer som indsætninger, opdateringer eller sletninger.

Selvfølgelig som en påmindelse – hver vertex i forretningsreglen repræsenterer en atomar kommando. Den gemmes i RDBMS-tabellen som en post med attributter som f.eks. kommandotype, beskrivelse og andre supplerende data. I et træ har hvert toppunkt en og kun en forælder (undtagen rodpunktet, som ikke har nogen forælder), og derfor bør hver post indeholde et ID for det overordnede toppunkt. Det er også praktisk at have en anden tabel, der indeholder regelposterne med de data, der er relevante for selve forretningsreglen. Der er ikke noget problem med at lagre forretningsreglens datakonstruktioner af nogen kompleksitet med denne fremgangsmåde.

Den CRUD-operationer er temmelig ligetil. Ændringer af forretningsreglen kan kræve opdateringer af en eller begge tabeller – regel eller kommando. Ved sletning eller indsættelse af kommandoer er det nødvendigt at vedligeholde referencerne mellem kommandoerne (det er i det væsentlige at slette eller indsætte knuder i et træ).

En af BRMS-komponenterne, lad os kalde den en manager, skal udføre de beskrevne databaseoperationer og levere et API til CRUD-operationer på forretningsregler.

Behandlingen af forretningsreglen

Behandlingen af forretningsreglerne starter, når en bestemt forretningsbegivenhed sker. Det kan være hvad som helst – en bruger har logget ind, et køb er blevet foretaget, et beløb er blevet overført osv. Denne form for aktivitet bør spores, og BRMS bør informeres om den via en eller anden transport. AMQP er højst sandsynligt bedst egnet til denne form for opgave.

1. Hele konceptet er bygget på en mikroservicearkitektur. Forretningsbegivenhedsforbrugeren microservice lytter til alle forretningsbegivenheder via deklaration af en kø og binding af den til en specifik udveksling på en RabbitMQ-udvekslingsserver. Når en forretningsaktivitet (som anses for at være vigtig og følges) sker i det primære softwaresystem, sendes meddelelsen til RabbitMQ-udvekslingsserveren. Den indeholder oplysninger om, hvad der er sket, samt nogle relevante supplerende data. Forretningsbegivenheden kan identificeres med en attribut af en hvilken som helst art, der overføres i meddelelsen eller anvendes som en routingnøgle, f.eks. en streng purchase.completed. Meddelelsen forbruges derefter af BRMS-forretningsbegivenhedsforbruger-microservice.

2. Når forretningsbegivenhedsforbruger-microservice får meddelelsen fra hovedsoftwaresystemet, forespørger den derefter manager-microservice, om der er nogen forretningsregler i databasen, der har den relevante regeludløser for forretningsaktivitetsbegivenheden. Og hvis der er en sådan matchende forretningsregel, returnerer manager-microservice de oprindelige kommandodata til business event consumer-microservice. Denne datahentning fra manager sker via gRPC og er visualiseret med en stiplet linje.

3. Lige efter at manager-microservice har svaret med de indledende kommandodata, er business event consumer-microservice klar til at initialisere behandlingen af forretningsreglen. Forretningsbegivenhedsforbrugeren danner en anden meddelelse, som indkapsler de indledende kommandodata (modtaget fra manager-microservice) og dataene fra forretningsbegivenheden, som er modtaget fra hovedsoftwaresystemet. Den sender den via AMQP til en intern BRMS-udveksling. Meddelelsens routingnøgle svarer til kommandotypen.

4. Den indledende kommandobehandlingsmikroservice forbruger meddelelsen (den lytter til den kø, hvor meddelelserne med routingnøgle initial er stablet). Derefter udfører den sin logik (i et grundlæggende tilfælde huser indledende blok ingen logik) og forespørger manager, om der er efterfølgende kommandoer i forretningsreglen (det er de kommandoer med parent_id lig med id for den kommando, der er under behandling). Og hvis det er tilfældet, modtager den de næste kommandodata og sender både forretningsbegivenhedsdata og næste kommandodata til den interne RabbitMQ-server. Ja, det ligner nu linket list traversal, og når reglen har grene, er det en tree traversal! Det er sådan, at forretningsreglen behandles kommando for kommando. En anden vigtig ting her – i denne sammenhæng videregives forretningsbegivenhedsdataene til hver enkelt underordnede kommando. Det er en kontekst for den unikke udførelse af forretningsreglen. Den kan bruges senere i dataanalysekommandoprocessoren og handlingskommandoprocessoren.

Til illustration lad os antage, at eksempelreglen har en struktur som denne: indledende kommando -> betinget dataanalysekommando -> forretningshandlingskommando. Så er den næste kommando efter initial kommandoen dataanalysekommandoen.

5. Analysekommandoprocessoren forbruger meddelelsen med routingnøglen analysis fra den interne udveksling. Baseret på evalueringen af de betingelser, der er beskrevet i analysekommandoen for forretningsreglen, og ved hjælp af forretningsbegivenhedsdataene, kan regeludførelsesflowet fortsætte eller stoppe her. Hvis den stopper – bliver der ikke udført yderligere forretningsregelkommandoer. Hvis udførelsesflowet fortsætter, forespørger analysekommandoprocessoren manager om de næste forretningsregelkommandoer, henter dem og offentliggør endnu en meddelelse til den interne udvekslingsserver.

6. Endelig er der en meddelelse i den interne udveksling, som er klar til at blive forbrugt af handlingskommandoprocessoren. Hvis forretningsreglens udførelsesflow er nået så langt til denne kommando, betyder det, at i denne gren af reglen var alle betingelser, som var der i dataanalysekommandoen, sandfærdige, og udførelsesflowet blev ikke afbrudt. Handlingskommandoprocessoren udfører handlingen, f.eks. sender en e-mail.

Denne form for graftraversering er dybdeførst, og når en kommando med 2 eller flere underordnede kommandoer påtræffes, begynder den samtidige dybdeførst-traversering for hver gren på grund af den asynkrone karakter af forretningsregelbehandlingen i det beskrevne system.

Skalering

Den beskrevne fremgangsmåde muliggør ikke blot en stor adskillelse af bekymringer, men kan også spare mange penge, når det kommer til at betale IaaS-regningerne. Slutbrugerne opretter en række forretningsregler med forskelligt antal kommandoer af forskellig art og forskelligt antal forgreninger. Men de almindelige skaleringsscenarier er som følger:
1. Antallet af forretningshændelser stiger – forretningshændelsesforbrugeren skalerer op.
2. Antallet af forretningsregler, der er tilknyttet (udløst) af forretningshændelserne, stiger – den oprindelige kommandoprocessor skalerer op sammen med lederen.
3. Der er mange analysekommandoer i forretningsreglerne – analysekommandoprocessoren skalerer op
4. Der skal udføres for mange handlingskommandoer – handlingskommandoprocessoren skalerer op.

Troværdighed

Systemets blodkar er transporten. For at systemet kan forblive funktionsdygtigt under høj belastning, skal den interne udveksling af meddelelser være meget pålidelig. RabbitMQ tilbyder clustering og opfylder kravene til pålidelighed godt (https://www.rabbitmq.com/clustering.html).

Andere kommandotyper

Der kan indføres enhver anden forretningslogik i systemet. En af de populære og efterspurgte kommandotyper er en kommandotype “ventetid” (f.eks. “Vent i 45 minutter, fortsæt derefter”). Med indførelsen af kommandoen “time-wait” er behandlingen af forretningsreglen ikke længere realtidsbehandling, da den kan blive suspenderet i et stykke tid. Sådanne ændringer kræver yderligere kommandoprocessorer og nogle få justeringer af datastrukturerne, som ligger uden for rammerne af denne tekst. Det kan være vanskeligt at rode med tiden, og det kan være en udfordring at skrive en tjeneste, der betjener tidsplaner og tid, her er et eksempel på en god tjeneste: https://github.com/nextiva/krolib

Til alternativer fra tredjepart

Der findes velkendte alternativer af regelmotorer/workflowmotorer, her er top 3 af dem (IMHO):
1. Comunda – det er et modent produkt med community- og enterprise-versioner, som du måske ønsker at bruge. Det er klart, at enterprise-versionen er betalt.
2. Luigi – det er et workflow engine-værktøj, der er udviklet af Spotify til deres interne behov, men som allerede bruges af snesevis af andre virksomheder.
3. Apache Airflow – det er et andet velkendt produkt, der har vist sig at være kompetent, praktisk og tilpasselig.

Det, der forener disse værktøjer, er, at de alle bruger direkte acykliske grafer som den datastruktur, der repræsenterer forretningsreglerne eller workflows. Det er ikke nogen overraskelse.

Der kan være andre produkter, der er værd at være opmærksom på, men enhver undersøgelse bør starte med disse tre.

Konklusion

Det kan være udfordrende at opbygge sin egen business rules engine, men det er givende. Ikke alene får du et internt system, men det er også bygget efter de specifikke krav, som din virksomhed har. Et godt DevOps-team er et must, når det drejer sig om at opretholde pålidelighed, skalerbarhed og overvågning. Når alt kommer til alt, får du et fantastisk produkt, som du kan være stolt af.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.