Controlelijst voor prestatie-efficiëntie
Efficiëntie van prestaties is de mogelijkheid van uw workload om op een efficiënte manier te voldoen aan de eisen die gebruikers stellen en is een van de pijlers van het Microsoft Azure Well-Architected Framework. Gebruik deze controlelijst om uw toepassingsarchitectuur te controleren vanuit het oogpunt van prestatie-efficiëntie.
Toepassingsontwerp
Partitioneren van de workload. Ontwerp delen van het proces zo dat ze discrete en ontcomposeerbare onderdelen zijn. Minimaliseer de grootte van elk onderdeel, terwijl u de gebruikelijke regels voor scheiding van problemen en het principe van één verantwoordelijkheid volgt. Hierdoor kunnen de onderdelen zodanig worden gedistribueerd dat het gebruik van elke rekeneenheid (zoals een rol- of databaseserver) wordt gemaximaliseerd. Het maakt het ook gemakkelijker om de toepassing te schalen door exemplaren van specifieke resources toe te voegen. Voor complexe domeinen kunt u overwegen om een microservicesarchitectuur te gebruiken.
Ontwerp voor het schalen van. Door te schalen kunnen toepassingen reageren op variabele belasting door het aantal instanties van rollen, wachtrijen en andere services die ze gebruiken, te verhogen en te verlagen. De toepassing moet echter met dit doel worden ontworpen. De toepassing en de services die de toepassing gebruikt, moeten bijvoorbeeld staatloos zijn, zodat aanvragen naar een instantie kunnen worden gerouteerd. Dit voorkomt ook dat het optellingen of verwijderen van specifieke instanties nadelige gevolgen heeft voor huidige gebruikers. U moet ook de configuratie of autodetection van exemplaren implementeren wanneer deze worden toegevoegd en verwijderd, zodat code in de toepassing de benodigde routering kan uitvoeren. Een webtoepassing kan bijvoorbeeld gebruikmaken van een set wachtrijen in een round robin-benadering om aanvragen te routeer naar achtergrondservices die worden uitgevoerd in werkrollen. De webtoepassing moet wijzigingen in het aantal wachtrijen kunnen detecteren om aanvragen te kunnen routeren en de belasting van de toepassing te kunnen balanceren.
Schaal als eenheid. Plan extra resources om groei mogelijk te maken. Voor elke resource kent u de bovenste schaallimieten en gebruikt u sharding of uitcompositie om deze limieten te overschrijden. Bepaal de schaaleenheden voor het systeem in termen van goed gedefinieerde sets resources. Dit maakt het eenvoudiger om uitschaalbewerkingen toe te passen en minder gevoelig voor negatieve gevolgen voor de toepassing door beperkingen die worden opgelegd door een gebrek aan resources in een deel van het algehele systeem. Als u bijvoorbeeld een aantal van x web- en werkrollen toevoegt, is mogelijk een aantal van y extra wachtrijen en z opslagaccounts vereist om de extra werkbelasting te verwerken die door de rollen wordt gegenereerd. Een schaaleenheid kan dus bestaan uit x web- en werkrollen, y wachtrijen en z-opslagaccounts. Ontwerp de toepassing zodat deze eenvoudig kan worden geschaald door een of meer schaaleenheden toe te voegen. Overweeg het patroon Implementatiestempels te gebruiken om schaaleenheden te implementeren.
Vermijd client-affiniteit. Zorg er waar mogelijk voor dat de toepassing geen affiniteit vereist. Aanvragen kunnen dus worden gerouteerd naar een instantie en het aantal exemplaren is niet relevant. Dit voorkomt ook de overhead van het opslaan, ophalen en onderhouden van statusinformatie voor elke gebruiker.
Profiteer van functies voor automatisch schalen van platformen. Waar het hostingplatform ondersteuning biedt voor een mogelijkheid voor automatisch schalen, zoals Automatisch schalen van Azure, geeft u de voorkeur aan aangepaste mechanismen of mechanismen van derden, tenzij het ingebouwde mechanisme niet aan uw vereisten kan voldoen. Gebruik waar mogelijk geplande regels voor schalen om ervoor te zorgen dat resources beschikbaar zijn zonder opstartvertraging, maar voeg waar nodig reactieve automatische schaalvergroting toe aan de regels om te kunnen omgaan met onverwachte wijzigingen in de vraag. U kunt de bewerkingen voor automatisch schalen in het klassieke implementatiemodel gebruiken om automatisch schalen aan te passen en aangepaste tellers toe te voegen aan regels. Zie Richtlijnen voor automatisch schalen voor meer informatie.
Offload CPU-intensieve en I/O-intensieve taken als achtergrondtaken. Als een aanvraag bij een service naar verwachting lang duurt om aanzienlijke resources uit te voeren of te verwerken, offloadt u de verwerking voor deze aanvraag naar een afzonderlijke taak. Gebruik werkrollen of achtergrondtaken (afhankelijk van het hostingplatform) om deze taken uit te voeren. Met deze strategie kan de service verdere aanvragen blijven ontvangen en responsief blijven. Zie Richtlijnen voor achtergrondtaken voor meer informatie.
Distribueren van de workload voor achtergrondtaken. Wanneer er veel achtergrondtaken zijn, of de taken veel tijd of resources vereisen, verspreidt u het werk over meerdere rekeneenheden (zoals werkrollen of achtergrondtaken). Zie het patroon Concurrerende consumenten voor een mogelijke oplossing.
Overweeg om over te gaan naar een shared-nothing architectuur. Een architectuur zonder gedeelde inhoud maakt gebruik van onafhankelijke, zelfvoorzienende knooppunten zonder single point of content (zoals gedeelde services of opslag). In theorie kan een dergelijk systeem bijna voor onbepaalde tijd worden geschaald. Hoewel een volledig gedeelde niets-benadering doorgaans niet praktisch is voor de meeste toepassingen, kan het mogelijkheden bieden om te ontwerpen voor betere schaalbaarheid. Het vermijden van het gebruik van sessietoestanden aan de serverzijde, client-affiniteit en gegevenspartities zijn bijvoorbeeld goede voorbeelden van het verplaatsen naar een shared-nothing-architectuur.
Gegevensbeheer
Gebruik gegevenspartitie. Verdeel de gegevens over meerdere databases en databaseservers, of ontwerp de toepassing voor het gebruik van gegevensopslagservices die deze partitionering transparant kunnen bieden (voorbeelden zijn Azure SQL Database Elastische database en Azure Table Storage). Deze aanpak kan helpen om de prestaties te maximaliseren en eenvoudiger te schalen. Er zijn verschillende partitioneringstechnieken, zoals horizontaal, verticaal en functioneel. U kunt een combinatie van deze gebruiken om maximaal te profiteren van verbeterde queryprestaties, eenvoudigere schaalbaarheid, flexibeler beheer, betere beschikbaarheid en om het type opslag af te spelen op de gegevens die het zal bevatten. Overweeg ook om verschillende soorten gegevensopslag te gebruiken voor verschillende typen gegevens, door de typen te kiezen op basis van hoe goed ze zijn geoptimaliseerd voor het specifieke gegevenstype. Dit kan bestaan uit het gebruik van Table Storage, een documentdatabase of een gegevensopslag van een kolomfamilie, in plaats van, of, evenals een relationele database. Zie Richtlijnen voor gegevenspartities voor meer informatie.
Ontwerp voor uiteindelijke consistentie. Uiteindelijke consistentie verbetert de schaalbaarheid door de benodigde tijd voor het synchroniseren van gerelateerde gegevens die zijn gepartitief over meerdere winkels te verminderen of te verwijderen. De kosten zijn dat gegevens niet altijd consistent zijn wanneer ze worden gelezen en dat sommige schrijfbewerkingen conflicten kunnen veroorzaken. Uiteindelijke consistentie is ideaal voor situaties waarin dezelfde gegevens vaak worden gelezen, maar niet vaak worden geschreven. Zie Data Consistency Primer (Primer voor gegevensconsistentie) voor meer informatie.
Verminder chatty interacties tussen onderdelen en services. Vermijd het ontwerpen van interacties waarbij een toepassing meerdere aanroepen naar een service moet maken (die elk een kleine hoeveelheid gegevens retourneren), in plaats van één aanroep die alle gegevens kan retourneren. Combineer waar mogelijk verschillende gerelateerde bewerkingen in één aanvraag wanneer de aanroep naar een service of onderdeel is met een merkbare latentie. Dit maakt het gemakkelijker om prestaties te bewaken en complexe bewerkingen te optimaliseren. Gebruik bijvoorbeeld opgeslagen procedures in databases om complexe logica in te kapselen en het aantal retouren en resourcevergrendeling te verminderen.
Gebruik wachtrijen om de belasting voor gegevens schrijven met hoge snelheid te levelen. Pieken in de vraag naar een service kunnen die service overbelasten en leiden tot escalatiefouten. U kunt dit voorkomen door het patroon Load Leveling op basisvan een wachtrij te implementeren. Gebruik een wachtrij die fungeert als een buffer tussen een taak en een service die wordt aanroept. Dit kan onregelmatige zware belastingen soepel laten verlopen, wat er anders toe kan leiden dat de service mislukt of dat er een time-out voor de taak is.
Minimaliseer de belasting van het gegevensopslag. Het gegevensopslag is vaak een verwerkingsknelpunt, een kostbare resource en is vaak niet eenvoudig uit te schalen. Waar mogelijk verwijdert u logica (zoals het verwerken van XML-documenten of JSON-objecten) uit het gegevensopslag en voert u de verwerking binnen de toepassing uit. In plaats van XML bijvoorbeeld door te geven aan de database (anders dan als een ondoorzichtige tekenreeks voor opslag), serialiseert of deserialiseert u de XML binnen de toepassingslaag en geeft u deze door in een formulier dat in het gegevensopslag is opgeslagen. Het is doorgaans veel eenvoudiger om de toepassing uit te schalen dan het gegevensopslag. Probeer daarom zo veel mogelijk rekenintensieve verwerking uit te proberen binnen de toepassing.
Minimaliseer de hoeveelheid opgehaalde gegevens. Haal alleen de gegevens op die u nodig hebt door kolommen op te geven en criteria te gebruiken om rijen te selecteren. Gebruik tabelwaardeparameters en het juiste isolatieniveau. Gebruik mechanismen zoals entiteitstags om te voorkomen dat gegevens onnodig worden opgehaald.
Gebruik caching op een agressieve manier. Gebruik waar mogelijk caching om de belasting te verminderen van resources en services die gegevens genereren of leveren. Caching is doorgaans geschikt voor gegevens die relatief statisch zijn of die aanzienlijke verwerking vereisen om te verkrijgen. Caching moeten op alle niveaus plaatsvinden, indien van toepassing in elke laag van de toepassing, inclusief gegevenstoegang en het genereren van de gebruikersinterface. Zie de Caching Guidance (Richtlijnen voor caching) voor meer informatie.
Gegevensgroei en -retentie verwerken. De hoeveelheid gegevens die door een toepassing wordt opgeslagen, neemt in de tijd toe. Deze groei verhoogt de opslagkosten en de latentie bij het openen van de gegevens, wat van invloed is op de doorvoer en prestaties van de toepassing. Het kan mogelijk zijn om regelmatig een deel van de oude gegevens te archiveren die niet meer worden gebruikt of om gegevens die zelden worden gebruikt, te verplaatsen naar langetermijnopslag die rendabeler is, zelfs als de toegangslatentie hoger is.
Optimaliseer DTO's (Data Transfer Objects) met behulp van een efficiënte binaire indeling. DMO's worden vaak tussen de lagen van een toepassing doorgegeven. Het minimaliseren van de grootte vermindert de belasting van resources en het netwerk. U kunt de besparingen echter in balans brengen met de overhead van het converteren van de gegevens naar de vereiste indeling op elke locatie waar deze worden gebruikt. Gebruik een indeling met de maximale interoperabiliteit om een onderdeel eenvoudig opnieuw te kunnen gebruiken.
Stel cachebeheer in. Ontwerp en configureer de toepassing om waar mogelijk gebruik te maken van uitvoer-caching of fragment-caching, om de verwerkingsbelasting te minimaliseren.
Schakel caching aan clientzijde in. Webtoepassingen moeten cache-instellingen inschakelen voor de inhoud die in de cache kan worden opgeslagen. Dit is doorgaans standaard uitgeschakeld. Configureer de server om de juiste cachebesturingsheaders te leveren, zodat inhoud op proxyservers en clients in de cache kan worden opgeslagen.
Gebruik Azure Blob Storage en de Azure Content Delivery Network om de belasting van de toepassing te verminderen. Overweeg statische of relatief statische openbare inhoud, zoals afbeeldingen, resources, scripts en stijlbladen, op te slaan in blobopslag. Met deze aanpak wordt de toepassing van de belasting die wordt veroorzaakt door het dynamisch genereren van deze inhoud voor elke aanvraag, ontlast. Overweeg daarnaast het gebruik van de Content Delivery Network om deze inhoud in de cache op te nemen en aan clients te leveren. Het gebruik Content Delivery Network de prestaties van de client verbeteren omdat de inhoud wordt geleverd vanuit het geografisch dichtstbijzijnde datacenter dat een Content Delivery Network cache bevat. Zie de Content Delivery Network voor meer informatie.
Optimaliseer en stem SQL query's en indexen af. Sommige T-SQL instructies of constructies hebben mogelijk een negatief effect op de prestaties die kunnen worden verminderd door de code in een opgeslagen procedure te optimaliseren. Vermijd bijvoorbeeld het converteren van datum/tijd-typen naar een varchar voordat u vergelijkt met een letterlijke waarde voor datum/tijd. Gebruik in plaats daarvan vergelijkingsfuncties voor datum/tijd. Het ontbreken van de juiste indexen kan ook de uitvoering van query's vertragen. Als u een framework voor object-/relationele toewijzing gebruikt, moet u begrijpen hoe het werkt en hoe dit van invloed kan zijn op de prestaties van de gegevenstoegangslaag. Zie Query's afstemmen voor meer informatie.
Overweeg om gegevens te denormaliseren. Gegevensnormalisatie helpt duplicatie en inconsistentie te voorkomen. Het onderhouden van meerdere indexen, het controleren op referentiële integriteit, het uitvoeren van meerdere toegang tot kleine hoeveelheden gegevens en het samenvoegen van tabellen om de gegevens opnieuw samen te stellen, brengt echter een overhead met zich mee die van invloed kan zijn op de prestaties. Overweeg of een extra opslagvolume en duplicatie acceptabel zijn om de belasting van het gegevensopslag te verminderen. Overweeg ook of de toepassing zelf (die doorgaans eenvoudiger te schalen is) kan worden vertrouwd om taken over te nemen, zoals het beheren van referentiële integriteit om de belasting van het gegevensopslag te verminderen. Zie Richtlijnen voor gegevenspartities voor meer informatie.
Implementatie
Bekijk de antipatroonprestaties. Zie Antipatroon prestaties voor cloudtoepassingen voor algemene procedures die waarschijnlijk schaalbaarheidsproblemen zullen veroorzaken wanneer een toepassing onder druk staat.
Gebruik asynchrone aanroepen. Gebruik waar mogelijk asynchrone code bij het openen van resources of services die kunnen worden beperkt door I/O- of netwerkbandbreedte, of die een merkbare latentie hebben, om te voorkomen dat de aanroepende thread wordt vergrendeld.
Vermijd het vergrendelen van resources en gebruik in plaats daarvan een optimistische benadering. Vergrendel nooit de toegang tot resources, zoals opslag of andere services met een merkbare latentie, omdat dit een primaire oorzaak van slechte prestaties is. Gebruik altijd optimistische benaderingen voor het beheren van gelijktijdige bewerkingen, zoals het schrijven naar de opslag. Gebruik functies van de opslaglaag om conflicten te beheren. In gedistribueerde toepassingen kunnen gegevens uiteindelijk alleen consistent zijn.
Comprimeren van zeer gecomprimeerde gegevens via netwerken met een hoge latentie en lage bandbreedte. In de meeste gevallen in een webtoepassing is het grootste volume aan gegevens dat door de toepassing wordt gegenereerd en via het netwerk wordt doorgegeven HTTP-antwoorden op clientaanvragen. HTTP-compressie kan dit aanzienlijk verminderen, met name voor statische inhoud. Dit kan de kosten verlagen en de belasting op het netwerk verminderen, hoewel het comprimeren van dynamische inhoud wel een fractioneel hogere belasting op de server met zich mee kan brengen. In andere, meer gealeraliseerde omgevingen kan gegevenscompressie de hoeveelheid verzonden gegevens verminderen en de overdrachtstijd en -kosten minimaliseren, maar de compressie- en decompressieprocessen zorgen voor overhead. Daarom mag compressie alleen worden gebruikt wanneer er sprake is van een aantoonbare prestatieverbetering. Andere serialisatiemethoden, zoals JSON of binaire coderingen, kunnen de payloadgrootte verminderen en minder invloed hebben op de prestaties, terwijl xml waarschijnlijk zal toenemen.
Minimaliseer de tijd dat verbindingen en resources in gebruik zijn. Onderhoud verbindingen en resources alleen zolang u ze nodig hebt. Open bijvoorbeeld verbindingen zo laat mogelijk en laat ze zo snel mogelijk terug naar de verbindingsgroep. U kunt resources zo laat mogelijk verkrijgen en zo snel mogelijk verwijderen.
Minimaliseer het aantal vereiste verbindingen. Serviceverbindingen nemen resources over. Beperk het vereiste aantal en zorg ervoor dat bestaande verbindingen waar mogelijk opnieuw worden gebruikt. Gebruik bijvoorbeeld na het uitvoeren van verificatie waar nodig imitatie om code uit te voeren als een specifieke identiteit. Dit kan helpen om optimaal gebruik te maken van de verbindingsgroep door verbindingen opnieuw te gebruiken.
Notitie
API's voor sommige services hergebruiken verbindingen automatisch, mits servicespecifieke richtlijnen worden gevolgd. Het is belangrijk dat u de voorwaarden begrijpt die het hergebruik van verbindingen mogelijk maken voor elke service die door uw toepassing wordt gebruikt.
Verzend aanvragen in batches om het netwerkgebruik te optimaliseren. Verzend en lees bijvoorbeeld berichten in batches bij het openen van een wachtrij en voer meerdere lees- of schrijfberichten uit als batch bij het openen van opslag of een cache. Dit kan helpen de efficiëntie van de services en gegevensopslag te maximaliseren door het aantal aanroepen via het netwerk te verminderen.
Vermijd waar mogelijk een vereiste om de sessietoestand aan de serverzijde op te slaan. Sessietoestandbeheer aan de serverzijde vereist doorgaans client-affiniteit (dat wil zeggen, elke aanvraag routeren naar hetzelfde server-exemplaar), wat van invloed is op de mogelijkheid van het systeem om te schalen. In het ideale moment moet u clients zo ontwerpen dat ze staatloos zijn ten opzichte van de servers die ze gebruiken. Als de toepassing echter de sessietoestand moet behouden, gevoelige gegevens of grote hoeveelheden gegevens per client moet opslaan in een gedistribueerde cache aan de serverzijde waar alle exemplaren van de toepassing toegang toe hebben.
Optimaliseer tabelopslagschema's. Wanneer u tabelopslag gebruikt waarvoor de tabel- en kolomnamen moeten worden doorgegeven en verwerkt met elke query, zoals Azure Table Storage, kunt u overwegen kortere namen te gebruiken om deze overhead te verminderen. Het is echter niet erg leesbaar of beheersbaar als u te compacte namen gebruikt.
Maak resourceafhankelijkheden tijdens de implementatie of bij het opstarten van de toepassing. Vermijd herhaalde aanroepen naar methoden die het bestaan van een resource testen en maak vervolgens de resource als deze nog niet bestaat. Methoden zoals CloudTable.CreateIfNotExists en CloudQueue.CreateIfNotExists in de Azure Storage clientbibliotheek volgen dit patroon. Deze methoden kunnen aanzienlijke overhead met zich mee brengen als ze worden aangeroepen vóór elke toegang tot een opslagtabel of opslagwachtrij. In plaats daarvan:
- Maak de vereiste resources wanneer de toepassing wordt geïmplementeerd of wanneer deze voor het eerst wordt gestart (een enkele aanroep van CreateIfNotExists voor elke resource in de opstartcode voor een web- of werkrol is acceptabel). Zorg er echter voor dat u uitzonderingen verwerkt die zich kunnen voordoen als uw code probeert toegang te krijgen tot een resource die niet bestaat. In deze situaties moet u de uitzondering melden en mogelijk een operator waarschuwen dat er een resource ontbreekt.
- Onder bepaalde omstandigheden kan het geschikt zijn om de ontbrekende resource te maken als onderdeel van de code voor het afhandelen van uitzonderingen. Maar u moet voorzichtig zijn met deze benadering, omdat het niet bestaan van de resource kan duiden op een programmeerfout (bijvoorbeeld een verkeerd gespelde resourcenaam) of een ander probleem op infrastructuurniveau.
Gebruik lichtgewicht frameworks. Kies zorgvuldig de API's en frameworks die u gebruikt om het resourcegebruik, de uitvoeringstijd en de algehele belasting van de toepassing te minimaliseren. Het gebruik van web-API voor het afhandelen van serviceaanvragen kan bijvoorbeeld de footprint van de toepassing verminderen en de uitvoeringssnelheid verhogen, maar is mogelijk niet geschikt voor geavanceerde scenario's waarin de extra mogelijkheden van Windows Communication Foundation vereist zijn.
Overweeg het aantal serviceaccounts te minimaliseren. Gebruik bijvoorbeeld een specifiek account voor toegang tot resources of services die een limiet opleggen aan verbindingen of beter presteren wanneer er minder verbindingen worden onderhouden. Deze aanpak is gebruikelijk voor services zoals databases, maar kan van invloed zijn op de mogelijkheid om bewerkingen nauwkeurig te controleren als gevolg van de imitatie van de oorspronkelijke gebruiker.
Voer prestatieprofilering en belastingstests uit tijdens de ontwikkeling, als onderdeel van testroutines en vóór de definitieve release om ervoor te zorgen dat de toepassing naar eigen vermogen wordt uitgevoerd en geschaald. Deze tests moeten worden uitgevoerd op hetzelfde type hardware als het productieplatform, en met dezelfde typen en hoeveelheden gegevens en gebruikersbelasting als bij productie. Zie De prestaties van een cloudservice testen voor meer informatie.