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.
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.
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.

...men det er dyrt at lave god journalistik. Derfor beder vi dig overveje at tegne abonnement på Version2.
Digitaliseringen buldrer derudaf, og it-folkene tegner fremtidens Danmark. Derfor er det vigtigere end nogensinde med et kvalificeret bud på, hvordan it bedst kan være med til at udvikle det danske samfund og erhvervsliv.
Og der har aldrig været mere akut brug for en kritisk vagthund, der råber op, når der tages forkerte it-beslutninger.
Den rolle har Version2 indtaget siden 2006 - og det bliver vi ved med.