Best practices zonder server

Binnen de gemeenschap debatteren we al jaren over de best practices, maar er zijn een paar die het grootste deel van die tijd relatief geaccepteerd zijn.

De meeste beoefenaars zonder server die zich op deze praktijken abonneren, werken op schaal. De belofte van serverloos speelt zich meestal af op zowel grote schaal als zware werklasten in plaats van op een relatief laag niveau, dus veel van deze best practices komen uit de schaalhoek b.v. Nordstrom in de detailhandel en iRobot in IoT. Als je niet zo ver wilt schalen, kun je waarschijnlijk wegkomen zonder deze best practices toch te volgen.

En vergeet niet dat best practices niet 'de enige practices' zijn. Best practices zijn gebaseerd op een reeks onderliggende veronderstellingen. Als die veronderstellingen niet in uw gebruik passen, passen die best practices mogelijk niet.

Mijn belangrijkste veronderstelling is dat iedereen zijn applicatie bouwt om op schaal te kunnen werken (zelfs als het nooit op schaal wordt uitgevoerd).

Dus dit zijn mijn best practices zoals ik ze zie.

Elke functie zou slechts één ding moeten doen

Het gaat om functiefout en schaalisolatie.

Anders gezegd, als u een schakeloptie in uw functie gebruikt, doet u het waarschijnlijk verkeerd.

Veel tutorials en frameworks werken op basis van een grote monolithische functie achter een enkele proxyroute en gebruiken schakelinstructies. Ik houd niet van dit patroon. Het is niet goed schaalbaar en heeft de neiging grote en complexe functies te maken.

Het probleem met een / een paar functies die uw hele app uitvoeren, is dat wanneer u schaalt, u uiteindelijk uw hele applicatie schaalt, in plaats van het specifieke element te schalen.

Als u een deel van uw webtoepassing hebt dat 1 miljoen oproepen ontvangt en een ander deel dat duizend oproepen ontvangt, moet u uw functie voor de miljoen optimaliseren, terwijl u alle code voor de duizend moet opnemen. Dat is zonde en je kunt het niet gemakkelijk optimaliseren voor duizenden. Scheid ze uit. Daar zit zoveel waarde in.

Functies roepen geen andere functies op

Functies die andere functies aanroepen, is een antipatroon.

Er zijn maar weinig randgevallen waar dit een geldig patroon is, maar ze zijn niet gemakkelijk uit te splitsen.

Kortom, doe het niet. U verdubbelt eenvoudig uw kosten, maakt debuggen complexer en verwijdert de waarde van de isolatie van uw functies.

Functies moeten gegevens naar een gegevensopslag of wachtrij duwen, die een andere functie moet activeren als meer werk nodig is.

Gebruik zo weinig mogelijk bibliotheken in uw functies (bij voorkeur nul)

Deze lijkt me vanzelfsprekend.

Functies hebben een koude start (wanneer een functie voor de eerste keer wordt gestart) en een warme start (deze is gestart en is klaar om vanuit het warme zwembad te worden uitgevoerd). Koude start wordt beïnvloed door een aantal dingen, maar de grootte van het zip-bestand (of hoe de code ook wordt geüpload) maakt hier deel van uit. Ook het aantal bibliotheken dat moet worden geïnstantieerd.

Hoe meer code je hebt, hoe langzamer het is om koud te starten.

Hoe meer bibliotheken instantiëren nodig hebben, hoe langzamer het koud begint.

Java is bijvoorbeeld een briljant performante taal met een warme start op sommige platforms. Maar als u veel bibliotheken gebruikt, kunt u merken dat het vele seconden duurt om koud te starten. Je hebt ze vrijwel zeker niet nodig en koude startprestaties belemmeren niet alleen bij het opstarten maar ook bij het schalen.

Als een ander punt ben ik een groot voorstander van ontwikkelaars die alleen bibliotheken gebruiken wanneer dat nodig is en dat betekent beginnen met geen en eindigen met geen tenzij ik niet kan bouwen wat nodig is zonder een.

Dingen zoals express zijn gebouwd voor servers, en serverloze applicaties hebben niet alle elementen nodig. Dus waarom zou je alle code en afhankelijkheden introduceren? Waarom overbodige code invoeren? Het is niet alleen iets dat nooit zal worden uitgevoerd, maar het kan een beveiligingsrisico met zich meebrengen.

Er zijn zoveel redenen waarom dit een best practice is. Natuurlijk, als er een bibliotheek is die je hebt getest, kent en vertrouwt, breng hem dan absoluut binnen, maar het belangrijkste element is testen, kennen en vertrouwen in de code. Een tutorial volgen is niet hetzelfde.

Gebruik geen op verbindingen gebaseerde services, bijv. RDBMS

Gewoon niet tenzij het moet.

Deze brengt me in de meeste problemen. Veel webtoepassingsmensen zullen springen op de bandwagon "maar RDBMS zijn wat we weten".

Het gaat niet om RDBMS. Het gaat om de verbindingen.

Serverloos werkt het beste met services in plaats van verbindingen.

Services zijn bedoeld om reacties op verzoeken heel snel te retourneren en om de complexiteit van de gegevenslaag achter de service aan te kunnen. Dit is van grote waarde in de serverloze ruimte, en waarom zoiets als DynamoDB zo goed past binnen het serverloze paradigma.

Om eerlijk te zijn, serverloze mensen zijn niet tegen RDBMS, ze zijn tegen verbindingen. Verbindingen hebben tijd nodig en als u zich een schaalvergroting voorstelt, heeft elke functieomgeving een verbinding nodig en introduceert u zowel een knelpunt als een I / O in de koude start van de functie. Het is onnodig.

Dus als u een RDBMS moet gebruiken, maar een service plaatst die verbindingspooling in het midden afhandelt, is een autoschaalcontainer met een beschrijving eenvoudig te gebruiken, dat zou geweldig zijn.

Het grootste punt dat u hier moet maken, is dat het voor een serverloze architectuur wellicht nodig is om uw gegevenslaag opnieuw te bekijken. Dat is niet de fout van serverless. Als u probeert uw huidige gegevenslaag te hergebruiken en het werkt niet, dan is het waarschijnlijk een gebrek aan begrip van serverloze architecturen.

Eén functie per route (bij gebruik van HTTP)

Gebruik waar mogelijk de proxy met één functie niet. Het schaalt niet goed en helpt niet bij het isoleren van problemen. Er zijn gelegenheden waar u dit kunt vermijden, b.v. waar de functionaliteit van een reeks routes strikt is gekoppeld aan een enkele tabel en het is sterk losgekoppeld van de rest van de applicatie, maar dat is een randvoorwaarde in de meeste applicaties waarin ik heb gewerkt.

Dit voegt complexiteit toe in termen van beheer, maar het helpt echt in termen van isolatie van fouten en problemen wanneer uw toepassing schaalt. Begin zoals je verder wilt gaan.

Maar toen gebruikte je toch een soort configuratiebeheertool om alles uit te voeren, nietwaar? En je hebt al CI- en CD-tools gebruikt, toch? Je moet nog steeds DevOps gebruiken zonder server.

Leer berichten en wachtrijen te gebruiken (async FTW)

Serverloze applicaties werken meestal het beste wanneer de applicatie asynchroon is. Dit is niet eenvoudig voor webapplicaties waarbij de neiging bestaat om een ​​verzoek te beantwoorden en veel te vragen.

Terugkerend naar de functies die geen andere functies aanroepen, is het belangrijk erop te wijzen dat dit is hoe u functies samen koppelt. Een wachtrij fungeert als een stroomonderbreker in het chaining-scenario, zodat als een functie uitvalt, u eenvoudig een wachtrij kunt leegmaken die door een storing is geback-upt, of berichten die niet in een wachtrij met dode letter staan, kunt pushen.

Kortom, leer hoe gedistribueerde systemen werken.

Met client-applicaties met een serverloze back-end is de beste aanpak om naar CQRS te kijken. Het scheiden van het punt van het ophalen van gegevens van het punt van het invoeren van gegevens is de sleutel tot dit soort patroon.

Gegevensstromen, geen gegevensmeren

In een serverloos systeem stromen uw gegevens door uw systeem. Het kan in een gegevensmeer eindigen, maar de kans is groot dat het zich in uw serverloze systeem bevindt in een soort stroom. Behandel dus alle gegevens alsof ze in beweging zijn, op geen enkel moment in rust.

Het is niet altijd mogelijk, maar probeer te voorkomen dat u in een serverloze omgeving een zoekopdracht uitvoert vanuit een gegevensmeer.

Serverloos vereist dat u uw gegevenslaag aanzienlijk heroverweegt. Dit is de grootste gotcha met nieuwe mensen die zonder server komen en de neiging hebben om naar het RDBMS te reiken en plat te vallen, niet alleen omdat de schaal hen opvalt, maar hun datastructuren te snel te star worden.

U zult merken dat uw stromen zullen veranderen naarmate uw toepassing verandert en de schaal alles zal veranderen. Als het enige dat u hoeft te doen een doorstroming is, is het eenvoudig. Het is veel moeilijker om een ​​meer af te dammen.

Ik weet dat dit punt een beetje "daarbuiten" is dan anderen, maar het is niet eenvoudig om te maken.

Alleen coderen voor schaal is een vergissing, je moet overwegen hoe het schaalt

Het is heel eenvoudig om uw eerste serverloze applicatie te maken en deze te bekijken. Als je echter niet begrijpt wat je hebt gedaan, kun je gemakkelijk in de val lopen met elke andere oplossing voor automatisch schalen.

Als u niet nadenkt over uw toepassing en hoe deze wordt geschaald, stelt u zich voor op problemen. Als u iets maakt met een trage koude start (veel bibliotheken en bijvoorbeeld een RDBMS) en dan een piek in gebruik krijgt, kunt u de gelijktijdigheid van uw functie aanzienlijk verhogen en vervolgens uw verbindingen maximaliseren en uw toepassing vertragen naar beneden.

Dus, laat niet gewoon een applicatie vallen en stel je dan voor dat deze onder belasting hetzelfde werkt. Inzicht in uw applicatie onder belasting is nog steeds een deel van de taak.

Gevolgtrekking

Er zijn nog veel meer dingen die ik hier had kunnen doen en dit is mijn mening over de dingen die ik mensen het meest moet uitleggen als ik met ze praat.

Ik heb geen dingen genoemd zoals het plannen van uw applicatie, of het overwegen van de kosten van een applicatie of iets dergelijks, omdat dat enigszins buiten bereik is.

Ik kijk ernaar uit om de gedachten van anderen te horen. Ik ben er vrij zeker van dat ik een stroom mensen krijg die me vertelt dat ik het mis heb over RDBMS. Net als bij containers, heb ik geen hekel aan RDBMS, maar ik gebruik graag de juiste tools voor de juiste taken. Ken je gereedschap!