Invoering
Ik verliet Microsoft na 19 jaar, waar ik leiding gaf aan teams die systeemsoftware bouwden voor zeer schaalbare cloudapplicaties. Dit omvatte de leidende ontwikkeling van het Microsoft Orleans-framework vanaf het begin bij Microsoft Research totdat het een van de meest succesvolle open-sourceprojecten binnen het .NET-ecosysteem werd. Orleans drijft een aantal grootschalige Microsoft-systemen aan, zoals Xbox Game Services, Skype, Azure IoT, Azure ML, Azure Active Directory en nog veel meer cloudservices buiten Microsoft. Dus als je ooit online multiplayer-games zoals Halo of Call of Duty hebt gespeeld, heeft ons team een groot deel van de onderliggende infrastructuur gebouwd die dit ondersteunt.
Toen ik voor het eerst bij Orleans kwam, stond cloud computing nog in de kinderschoenen. We hadden een zicht van 10.000 voet en geen enkele regel code. We moesten opnieuw bedenken hoe applicaties op cloudschaal moesten worden gecodeerd, omdat beschikbare en krachtige schaalbare systemen op dat moment alleen door experts konden worden gerealiseerd. En hoewel iedereen wist dat de cloud eraan kwam, hadden we geen idee hoe we applicaties moesten bouwen op een manier die ervoor zorgde dat ze toegankelijk en productief zouden zijn voor miljoenen software-engineers.
De overkoepelende vraag – waar veel ontwikkelaars vandaag de dag nog steeds mee worstelen – was hoe de complexiteit die inherent is aan applicatie-ontwikkeling te verminderen. Uiteindelijk heb ik de helft van mijn carrière bij Microsoft doorgebracht om dit probleem op te lossen. Het antwoord was het ontwerpen van een programmeermodel dat zou veranderen hoe ontwikkelaars applicaties conceptualiseren, hoe ze code structureren en uiteindelijk wat voor soort mentale modellen ze bouwen, kijkend naar de problemen waarmee ze worden geconfronteerd. Die uitdaging trok mijn interesse gedurende de rest van mijn tijd bij Microsoft, en blijft tot op de dag van vandaag in mijn nieuwe rol bij Temporal.
Achtergrond
In het afgelopen decennium hebben tooling en infrastructuur zich snel ontwikkeld. Kubernetes, AWS en Azure om er maar een paar te noemen. Er zijn honderden verschillende services die ontwikkelaars kunnen helpen bij het bouwen van applicaties. Deze uitgebreide set van beschikbare kant-en-klare services maakte het eenvoudiger om geavanceerde applicatielogica te bouwen door gebruik te maken van de code van iemand anders in plaats van die van jezelf te schrijven. Maar tegelijkertijd maakte het onbedoeld cloud-applicaties nog meer verspreid dan voorheen.
Het is relatief eenvoudig om een gelukkig pad in applicatiecode te implementeren en te testen. Het moeilijkere deel is om ervoor te zorgen dat de code alle mogelijke storingscondities correct afhandelt. De moeilijkheidsgraad groeit exponentieel met het aantal externe afhankelijkheden waarmee de toepassing samenwerkt. Het is dezelfde uitdaging die er altijd al was, maar nu op een ander niveau van complexiteit.
Toen ik aan Orleans werkte, concentreerden we ons op het maken van een programmeermodel, waarbij het lijkt alsof je een enkele computer programmeert, maar het indien nodig zou uitbreiden naar tientallen of honderden servers. Het programmeermodel van Orleans is succesvol gebleken in het verminderen van de complexiteit van het bouwen van schaalbare clouddiensten. Het uitgangspunt van altijd beschikbare uniek adresseerbare objecten (korrels) resoneerde goed met een breed scala aan ontwikkelaars. Het gedeelte “altijd beschikbaar” hielp de applicatiecode betrouwbaarder te maken. Als een van de servers waarop de applicatie draait uitvalt, herstelt de applicatie zich snel en blijft deze draaien.
Het andere deel van de betrouwbaarheidsuitdaging – wat te doen als een aanroep van een afhankelijkheidsservice een fout retourneert – lieten we aan applicatieontwikkelaars over om op te lossen. Een deel van de reden waarom we daar geen oplossing probeerden aan te bieden, is dat het erg moeilijk is om er een te hebben die past bij het brede scala aan real-life scenario’s. En natuurlijk is het erg moeilijk om het goed te krijgen.
Ik schreef een paar maanden geleden een blogpost over de typische patronen van het omgaan met mislukkingen van externe oproepen hier: https://dev.to/temporalio/dealing-with-failure-5adf. Het toont de complexiteit en inherente compromissen van dit probleem, en dat is waar ontwikkelaars mee te maken hebben, naast het oplossen van de feitelijke zakelijke problemen. Ze worden gedwongen beslissingen te nemen over wat ze moeten doen als ze een foutmelding krijgen. Probeer ik het opnieuw? Meteen of met vertraging? Hoe vaak? Wat als ik crash tussen deze gesprekken door? Enzovoorts.
Het probleem afbakenen
Ik stond oog in oog met deze uitdagingen toen ik leiding gaf aan een team dat een kritieke service voor Xbox-games beheerde, een die een enorme hoeveelheid multiplayer-gameservers afhandelde. We wezen VM’s toe voor multiplayer-games zoals Forza, Halo en Minecraft, zodat spelers vanaf hun console konden meedoen en samen met hun vrienden konden spelen of konden concurreren met miljoenen andere spelers. Vanuit het perspectief van de spelers is het vanzelfsprekend dat alles onmiddellijk en soepel werkt. Maar aan de servicekant was het ontmoedigend.
Elke game vereist een VM die moet worden toegewezen en geconfigureerd. Vervolgens moet het worden voorzien van de gameservercode – gigabytes om te downloaden. Zodra alle vereiste bits op de VM staan, moet de gameserver starten en uiteindelijk melden dat hij klaar is voor een multiplayer-match. Zoals u zich kunt voorstellen, vereist elk van deze stappen meerdere externe oproepen die mogelijk mislukken. En op deze schaal falen ze regelmatig.
Gevraagde bewerkingen nemen tijd in beslag, van seconden tot minuten, en de servicecode moet anticiperen op fouten, bewerkingen die om onbekende redenen vastlopen, een beleid voor opnieuw proberen en opgeven, en een herstelplan voor het geval de servicecode halverwege opnieuw wordt opgestart . Dit is allemaal nog voordat een multiplayer-match op de gameserver is gestart. Daarna heeft de match zijn eigen levenscyclus die moet worden afgehandeld met vergelijkbare verwachtingen over mislukkingen.
Dit is een vereenvoudigde versie van het model, maar het geeft een klein kijkje in de lagere mechanica van het ontwikkelen van cloudservices, in dit geval voor games. Er zijn tegenwoordig vergelijkbare uitdagingen in vrijwel elke branche, of het nu gaat om financiële transacties, e-commerce, IoT, infrastructuurbeheer en nog veel meer.
Het komt allemaal terug naar de workflow
Als we het probleem dat applicatieontwikkelaars in al deze gevallen oplossen veralgemenen, kunnen we ze zien als workflows van verschillende soorten. Elke workflow is een bedrijfsproces met meerdere stappen of acties die moeten worden uitgevoerd tot ze zijn voltooid, ondanks incidentele mislukkingen van sommige ervan. Hoewel het bovenstaande voorbeeld specifiek is voor gaming, is het onderliggende probleem dat niet. Met de opkomst van gedistribueerde systemen merken programmeurs vaak dat ze dingen aan elkaar plakken en keer op keer dezelfde problemen aanpakken. Hoe zetten we clusters in? Hoe monitoren we ze? Hoe zetten we gedistribueerde databases in? Wat gebeurt er als we een foutmelding krijgen?
Elke ontwikkelaar kent wel een oplossing die er ongeveer zo uitziet:
Maar als we al deze lelijke complexiteit die geen echte zakelijke waarde toevoegt, verwijderen, kunnen we ons in plaats daarvan concentreren op de applicatielogica. Als we de boilerplate-code van ducttape vervangen door een transparant ingebouwd mechanisme, wordt dit schema veel eenvoudiger en veel eleganter. En dit is waar we mee bezig zijn Tijdelijk.
Voor mij is het een brede inspanning om ontwikkelaars te helpen kogelvrije applicaties te bouwen zonder alle onnodige steigers. In veel opzichten is het een voortzetting van wat me zo gepassioneerd maakte om aan Orleans te werken. Het doel is grotendeels hetzelfde: weggaan van de wereld waar miljoenen ontwikkelaars steeds opnieuw dezelfde betrouwbaarheidsproblemen moeten oplossen, naar een betere wereld van elegante code die het zakelijke probleem oplost. Tegenwoordig zien we veel standaardteksten die de focus weghalen van wat belangrijk is voor het bedrijf en de codebase vervuilen met duizenden en duizenden regels moeilijk te onderhouden code.
Microservice-architecturen, met al hun voordelen, maakten het probleem nog groter. De huidige benaderingen voor het werken met microservices voldoen gewoon niet aan de schaalbaarheids- en betrouwbaarheidsvereisten van moderne applicaties, en om te helpen hebben we een open-sourceoplossing voor microservice-orkestratie geïntroduceerd. En het is open source, MIT geen shenanigans.
Als je besluit het uit te proberen, hoor ik graag je openhartige feedback, ideeën en gedachten. Of als je geïnteresseerd bent om ons team te komen versterken, we zijn altijd op zoek naar ontwikkelaars die het leuk vinden om dit soort complexe uitdagingen op te lossen.
CreditSource link