Dagbog-bloggen

Looking glass - en microservice

Sidste blogindlæg handlede om pingtid, og hvorfor det er vigtigt at reducere denne.

Som så ofte før var den efterfølgende diskussion i kommentarsporet rigtig spændende, og den har nu ført til, at vi har indført gaming-profil på ADSL som et tilvalg for de kunder, som bor langt fra centralen og vægter pingtiden højt.

I dag skal det handle om, hvordan vi har bygget et looking glass, så man kan teste pingtiden til en given IP-adresse uden at være på Kviknets netværk.

Et looking glass (forstørrelsesglas) er et koncept, der er kendt fra mange større backbone-udbydere, som fx Cogent, Hurricane Electric og Telia.

Det er et værktøj, der bruges af netværksadministratorer, og det kan normalt udføre følgende funktioner:

  • Ping
  • Traceroute
  • Opslag i BGP-tabellen (den store, globale route-tabel)

Værktøjet giver således et indblik i hvordan internettet ser ud fra den specifikke udbyder og den lokation, man har valgt.

Det kan være yderst brugbart, hvis man skal undersøge, hvordan resten af verden ser på ens netværk her og nu - for eksempel, hvilken vej trafikken tager, om de rigtige IP-adresser er annonceret via BGP osv.

I første omgang skal vores looking glass primært bruges af avancerede superbrugere, som ikke har behov for opslag i BGP-tabellen.

Derfor går øvelsen på at stille ping og traceroute til rådighed via vores website, og vi skal også kunne give et estimat på, hvor høj en pingtid vil være, hvis man anvender en forbindelse fra en specifik adresse i Danmark.

Monolitisk arkitektur vs microservices

Hos Kviknet var vi fra starten af to udviklere, der skulle bygge vores CRM-system og website, og websitets funktion var udelukkende at agere salgskanal, mens CRM-systemets primære funktion var at danne regninger og opkræve penge fra kunderne.

Vi havde ingen forventning til, hvor stort firmaet egentlig ville blive, og derfor valgte vi at anvende en fælles database og en fælles kodebase. Derved kunne vi holde tidsforbruget på en minimum og genbruge så meget af hinandens kode som muligt.

Ideen var, at systemet skulle være så objektorienteret, som det praktisk var muligt, og vi skulle have revisionsspor på samtlige objekter.

Et revisionsspor må næsten anses for at være et ufravigeligt krav, når man har med regnskab og penge at gøre - det ville være en katastrofe, hvis vi ikke kunne spore kundernes betalinger eller mangel på samme, fordi en manuel fejl havde slettet eller ændret de relevante data.

En objektorienteret tilgang gør det nemt at indføre triggers og events forskellige steder i systemet - og fx sker opdateringen af revisionssporet i vores tilfælde i en central funktion i vores dataobjekt, som stort set alle andre objekter er nedarvet fra.

Når man har en fælles kodebase og en fælles database, er der tale om en monolitisk arkitektur.

Den er nemt at komme i gang med, da man skal bruge et minimum af servere, konfigurationer og udviklingstimer.

Til gengæld lider en monolitisk arkitektur af en række alvorlige svagheder, som man før eller siden støder på.

I driftsmæssig sammenhæng bliver systemet sårbart, når alt baseres på en enkelt database, og hvad værre er, kompleksiteten stiger med kvadratet af antallet af funktioner, da samtlige funktioner på grund af den fælles kodebase og database har potentiale til at gribe ind i hinanden.

Derfor kan det være meget svært at tilføje nye funktioner og nye udviklere til projektet, da en enkelt uheldig opdatering kan lægge hele systemet ned.

Løsningen på denne problemstilling kan være at basere dele af systemet på microservices, som i princippet kan operere autonomt i forhold til resten af systemet.

Vores første microservice - DHCP

Hos Kviknet blev en af vores første microservices vores DHCP-service, som vi tilføjede sidste forår, da vi begyndte at udbyde internet via eBSA.

DHCP-servicen er vital for driften af vores netværk, så derfor er den udskilt i sit eget system, som kan køre videre, selv om vores CRM-system skulle gå ned.

Vi har baseret DHCP-servicen på to stk. DHCP-servere og et databasecluster med to stk. MySQL-servere.

Kviknets DHCP-service

Databasen bag DHCP-servicen indeholder en liste over abonnenter og tilhørende IP-adresser, og denne liste opdateres en gang i minuttet med friske data fra vores CRM-system.

Går CRM-systemet ned, kører DHCP-servicen videre med den eksisterende liste, og kunderne vil således fortsat have adgang til nettet.

Ping og traceroute som microservice

Vi bygger vores looking glass som en microservice i PHP.

Kviknet looking glass service

Selv om purister med rette rynker på næsen af PHP, er store dele af vores system i dag baseret på PHP, og det er derfor et oplagt valg for os.

Ping er baseret på ICMP-pakker, og en simpel ping-funktion kan faktisk godt kodes i PHP. Det samme gælder traceroute, som både kan baseres på ICMP og på UDP, hvoraf sidstnævnte er standard på Linux.

Det er dog ikke portable, da de forskellige socket-flag er forskellige fra operativsystem til operativsystem, og hvad værre er, man skal tilsyneladende køre sit PHP-script med root-rettigheder, så det er udelukket at lave det som et standard PHP-script, der kaldes gennem en webserver.

Vi sparer derfor os selv for en del arbejde og kalder den indbyggede CLI-kommando på den underliggende Linux-boks med PHP's funktion til formålet og returnerer outputtet til brugeren.

Det er normalt en rigtig dårlig ide at kalde noget som helst CLI-baseret med data baseret på user input, men vi kan gøre en undtagelse her.

I og med at vi placerer vores pingtest på en separat server, kan vi isolere den fra resten af vores system, så skaden er begrænset, hvis uheldet er ude, og samtidig er det nemt at sanitize vores bruger-input, da en IP-adresse kun kan antage visse, veldefinerede former.

Hvis brugeren indtaster en IP-adresse, og den kan valideres, bruger vi den, som den er. Vi anvender PHP's filter_var-funktion til validering:

// IPv4
if (filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
  // Valid IPv4 address
}

Hvis brugeren derimod indtaster et hostnavn, foretager vi et DNS-opslag for at se, om vi kan finde en gyldig IP-adresse. Hvis det lykkedes, anvender vi IP-adressen i vores ping- eller traceroute-kommando.

Derved holder vi angrebsvektorerne på et minimum.

Når man laver en ping- eller traceroute-funktion som en webservice, skal man have en holdning til, om den skal vise status løbende, mens testen udføres, eller om den først skal vise et output, når testen er overstået.

Ping og traceroute kan i sagens natur tage lang tid, og for at holde det simpelt, har vi valgt først at vise output, når testen er overstået.

I visse tilfælde kan en traceroute ikke færdiggøres, da traceroute kan være blokeret undervejs til destinationsadressen, og derfor har vi sat en timeout på 25 sekunder på vores test.

Det er ud fra den præmis, at en traceroute, der ikke færdiggøres på under 25 sekunder, næppe kommer til at vise noget brugbart resultat alligevel.

Vi har også valgt at tilføje en estimat-funktion, der kan give et her-og-nu-billede af den pingtid, vores kunder i forskellige postnumre oplever.

Da der er tale om et gennemsnit af kunderne i et givent postnummer, er den selvfølgelig ikke helt præcis - i postnumre med mange kunder, der bor langt fra centralen og kører ADSL, vil pingtiden givetvis være højere, end hvis man tager et område med mange VDSL-kunder, der bor inden for få hundrede meter fra centralen.

Ikke desto mindre kan den give et billede af den generelle pingtid, og heldigvis passer det nogenlunde med teorien om, at pingtiden er en smule højere i Aalborg end i Odense.

Relateret indhold

Yoel Caspersens billede
Yoel Caspersen er direktør hos Kviknet, har en baggrund som udvikler og har gennem en længere årrække beskæftiget sig med udvikling af hostede PBX-løsninger, internetbutikker og software til online video- og tv-distribution. Dagbog-bloggen er en stafetblog for iværksættere.

Kommentarer (19)

Kommentarer (19)
Jens Jönsson

Kan rigtigt godt lide din estimeret PING tid. Sjovt at se at der er så stor forskel på postnumre der ligger tæt på hinanden (Jeg er med på at det kan være grundet kundersammensætningen)....

Folk tænker ikke på at der kan være lang vej fra dem til det de tror er nærmeste server...

Yoel Caspersen Blogger

Sjovt at se at der er så stor forskel på postnumre der ligger tæt på hinanden (Jeg er med på at det kan være grundet kundersammensætningen)....

Dels kan det være forskelle i sammensætningen af kunder, dels kan det være mindre forskelle i topologien i det underliggende access-netværk.

Tyndt befolkede postnumre (og dermed postnumre med få Kviknet-kunder) vil også give et mindre repræsentativt resultat, da hver enkelt kundes pingtid vil trække mere i gennemsnittet end det ville være tilfældet i et tættere befolket postnummer.

Yoel Caspersen Blogger

Hvad får dig til at tro det ?

Det afhænger jo primært af din egen forbindelse.....

I denne case har det jo intet at gøre med hans egen forbindelse, da han bruger vores looking glass. Det er derfor forbindelsen fra vores looking glass-server til hans lejede server i Tyskland, der åbenbart sender IPv6-pakker ud på en længere route.

Det passer med den generelle tendens i Tyskland, hvor IPv6-forbindelser har en smule højere latency end tilsvarende IPv4-forbindelser. Og det er det, der nok bliver bedre med tiden, når IPv6 når den kritiske masse og bliver den primære prioritet for udbyderne undervejs.

Anders Pallisgaard

blokeret undervejs til destinationsadressen, og derfor har vi sat en timeout på 25 sekunder

Denne løsning, med et blokerende eksternt kald og potentiel høj timeout, virker ikke særlig skalerbar, men måske er antallet af forespørgsler lavt?

Yoel Caspersen Blogger

Denne løsning, med et blokerende eksternt kald og potentiel høj timeout, virker ikke særlig skalerbar, men måske er antallet af forespørgsler lavt?

Du har ret i, at den ikke skalerer voldsomt godt, hvis der kommer mange samtidige brugere. Det ser dog ikke ud til at være et problem på nuværende tidspunkt, og jeg tvivler på, det nogensinde bliver et problem, da servicen primært henvender sig til eksisterende eller nye Kviknet-kunder, der lige skal checke pingtiden ud inden de bestiller.

Hvis man skulle lave servicen om, så shell-kaldet ikke blokerer, ville det være oplagt også at omskrive protokollen til API'et, så man starter jobbet og løbende poller for en status. Det ville også tillade en løbende opdatering af output-feltet efterhånden som tracerouten skrider frem.

Magnus Lund

Hos Kviknet var vi fra starten af to udviklere, der skulle bygge vores CRM-system og website, og websitets funktion var udelukkende at agere salgskanal, mens CRM-systemets primære funktion var at danne regninger og opkræve penge fra kunderne.

Kan det virkelig betale sig, at bygge sit eget faktureringssystem? Kunne det ikke bedre betale sig at integrere til et af de eksisterende systemer? Jeg er oprigtig nysgerrig - jeg er selv udvikler på et økonomisystem, og det griber virkelig hurtig om sig med need-to-have funktionalitet, når man når over, hvad man ellers kan klare i Excel. Alt sammen funktionalitet som er 99% ens på tværs af virksomheder - og som ikke direkte giver værdi til virksomheden.

Det har altid undret mig, at for eksempel 3 har bygget deres eget faktureringssystem - og som har enorme problemer, hvis man fx skifter fra privat til erhvervsabonnement - bare det at få en faktura ud af dem til den korrekte adresse er en udfordring.

Yoel Caspersen Blogger

Kan det virkelig betale sig, at bygge sit eget faktureringssystem?

Tja, om det kan betale sig afhænger nok af hvem man er, og hvilke ressourcer man har til sin rådighed. Hvis man har masser af penge, men skal købe udviklingstimerne ude i byen, er det nok bedst at forsøge at integrere til et eksisterende system.

Hvis man derimod er to udviklere, som ikke har nogen penge, ser billedet lidt anderledes ud :-)

Vi har fundet en fornuftig balance, hvor fakturadannelse, opkrævning og kreditering m.v. håndteres af vores CRM-system, mens det daglige finansbogholderi varetages af et af de alment kendte cloud-baserede bogholderi-systemer. Sumtal overføres hver måned fra CRM-systemet til finansbogholderiet i skyen, hvor vi så har simple, overskuelige posteringer i kontoplanen.

Anvendelsen af vores eget CRM-system har også givet os en anden, meget vigtig fordel: Vi kan selv tilføje rapporter, som vi har brug for - fx over periodisering, aktiveringer og afskrivninger, som vi bruger i stor stil pga. omkostningsstrukturen ved vores forretningstype.

Hvis man er ligeglad med, hvad eksterne parter synes om ens regnskab, afskriver man alle omkostninger så hurtigt som muligt, så man kan få skattefradrag og i øvrigt bruger så lidt tid på regnskabet som muligt.

Derved får man store underskud, når man bruger mange penge på vækst, og man har store overskud, når forretningen stagnerer og man tjener penge på den eksisterende kundebase uden at have udgifter til opstart af nye kunder.

Den slags er ikke så nemt, når man har eksterne långivere, som skal have forretningen til at passe ned i en typisk rating-model. Her må egenkapitalen ikke blive for lille, og derfor skal regnskabet afspejle den reelle værditilvækst, der sker, når man får en ny kunde i folden - uagtet at virksomheden starter med at have store omkostninger, der først er tjent hjem, når kunden har været kunde et stykke tid.

Så det at holde 100 % styr på kundebasens værdi er en vigtig parameter for vores CRM-system, og selv om der givetvis findes systemer derude, der kan gøre det for en, er det min vurdering, at vi har sparet mange penge på at udvikle den del af systemet selv.

Magnus Lund

Fair nok :-)

Min pointe var måske netop at når man kun har to udviklere, så var de bedre brugt på produkt-vendte aktiviteter, hvor I skal tjene pengene - og så betale de 100-200 kr. om måneden og outsource det "kedelige" (også af hensyn til revisionen, som ikke er super vilde med custom systemer, som de skal afstemme :-) ). Jeg er klar over at en integration også koster timer at bygge - men det må være billigere end at skulle lave det selv.

De fleste regnskabssystemer har end-points til at danne fakturaer, kreditnotaer osv. Jeg forstår godt værdien i at have helt styr på kundernes produkter og teknisk opsætning er bedre i et egenudviklet system (fordi det er en del af jeres konkurrencefordel at have styr på det). Men at have styr på momsopsætning, fakturalayouts, rykkere osv. giver jer ikke en konkurrencefordel.

Jens Jönsson

Min pointe var måske netop......

Der findes desværre ikke rigtigt nogen danske ERP systemer der er fantastisk gode til at håndtere abonnementer. De abonnement moduler de indeholder er ekstremt simple (Tro mig, jeg har været hele vejen rundt).
Selvom vi holder så meget som muligt på et minimum, så går det galt når der kommer for mange kunder i butikken. Og det er jo ikke lige meningen, vel :-)

Vi er derfor også i gang med at kode vores eget. Det bliver dog med API til et standard system.

Magnus Lund

Det ville være en kæmpe hjælp for mig at høre, hvad I mangler på et abonnementssystem. Jeg vil ikke sælge noget, men vores system er simpelt på det punkt, fordi vi ikke har en rigtig god case på det. Og jeg står gerne til rådighed med knowhow den anden vej (det lyder godt nok som om I har ret godt styr på det). Jeg kan nås på magnus@xena.biz.

Om ikke andet kan jeg skylde en øl i en lufthavn :-)

Yoel Caspersen Blogger

Det ville være en kæmpe hjælp for mig at høre, hvad I mangler på et abonnementssystem. Jeg vil ikke sælge noget, men vores system er simpelt på det punkt, fordi vi ikke har en rigtig god case på det.

Et godt abonnements-system til en ISP som vores skal kunne følgende:

  • Alt skal kunne ændres via API
  • Der skal kunne sættes en start- og en slutdato på et abonnement. Slutdatoen skal kunne være åben
  • Der skal være mulighed for at vælge en betalingsplan for kunden (betaling via betalingskort eller faktura) samt en definition af frekvensen (fx hver måned, hvert kvartal, halvår eller hele år) og en evt. buffer (hos Kviknet betaler man som standard 1 måned ad gangen, men 2 måneder forud)
  • Man skal kunne definere hvilke produkter, der indgår i abonnementet, og til hvilken pris
  • Man skal kunne override standard-indstillingen for produkter og pris i en periode (fx hvis man skal give kunden en bestemt pris de næste 3 måneder)
  • Fakturadato og betalingsdato skal kunne defineres på forhånd
  • Man skal kunne vælge om kunden skal have tilsendt faktura som PDF til en e-mail, eller om kunden skal logge ind på et website for at hente fakturaen
  • Systemet skal kunne håndtere mange tusinde kunder uden at man mister overblikket
  • Af samme grund skal de enkelte abonnements-fakturaer aggregeres i sum-tal, som overføres til finansbogholderiet. Det er håbløst at holde styr på fx 200.000 individuelle posteringer i finansbogholderiet når året er omme

Der er sikkert nogle ting, jeg har glemt, men det var, hvad jeg lige kunne ryste ud af ærmet.

Magnus Lund

Tusind tak for input, begge to! Det er interessant, at en ret stor udfordring fra jer begge er overskueligheden - altså alene mængden af data er en udfordring. Som jeg forstår jeres forretning er det, når der er rigtig mange små kunder, som hver især bidrager med en meget lille del af omsætningen og at alt skal automatiseres ud i 8nde led for at den enkelte kunde ikke ødelægger forretningen, at problemerne opstår.

Jeg tror ikke, I kommer ud over at skulle have jeres egne systemer, men måske kan der rykkes lidt med, hvor snittet lægges imellem standard-/økonomisystemet og specialsystemerne. Jeg fik i al fald noget at tænke på :-)

Anders Pallisgaard

ForeningLet.dk vil kunne løse (næsten) alle ovenstående ønsker fra Yoel. Den månedlige faktureringskørsel vil kunne opkræve via betalingskort (dankort/visa/mastercard/etc), Betalingsservice, MobilePay Invoice og EAN i én og samme kørsel. Der er et API til systemet til automatisk kundeoprettelse fra eksternt system, hvorefter kunden faktureres i henhold til det valgte abonnement.

Det sidste års tid er der dannet små 200.000 fakturaer i systemet, og det tal vokser hvert år.

Disclaimer: Jeg arbejder hos ForeningLet.dk.

Jens Jönsson

Systemet skal kunne håndtere mange tusinde kunder uden at man mister overblikket


Eksakt, der skal kunne søges meget bredt...

En udfordring for os med eksisterende system, er at én kunde kan have flere forbindelser, på flere forskellige adresser.
Det kan det ikke håndtere og vi er nødt til at oprette kunden flere gange. Det er træls....

Log ind eller opret en konto for at skrive kommentarer