Container Apps i AKS resolen com executar serveis que estan sempre disponibles. Però bona part del que fa Contoso Airlines no és així. Generar el PDF d'una targeta d'embarcament ocupa dos segons i passa quan un passatger confirma la seva reserva. Sincronitzar el catàleg de tarifes passa quan canvia un document a cosmos-contoso-tarifas-pro. Entre un esdeveniment i el següent no hi ha res a fer, i tanmateix avui Contoso paga per un contenidor encès esperant.
Azure Functions és la resposta: escrius una funció, declares què la dispara, i Azure s'encarrega d'executar-la quan toca i que no existeixi la resta del temps. Aquesta lliçó va més enllà de l'«hola món»: el model de desencadenadors i enllaços, els plans d'allotjament amb les seves contrapartides reals, les dues funcions de producció de Contoso, l'orquestració amb Durable Functions i la lliçó més dura del model, que és la idempotència.
Contingut
- Què és la computació sense servidor i què es paga
- Desencadenadors i enllaços: el model mental
- Plans d'allotjament comparats
- Crear el projecte i executar-lo en local
GenerarTarjetaEmbarque: la funció de la cuaSincronizarTarifas: la font de canvis de Cosmos DB- Configuració, identitat administrada i Key Vault
- Durable Functions i el flux de facturació en línia
- Idempotència, reintents, temps d'espera i límits
- Proves, desplegament i supervisió
- Quan NO fer servir funcions
- Errors Comuns i Consells
- Exercicis
- Conclusió
- Què és la computació sense servidor i què es paga
«Sense servidor» no vol dir que no hi hagi servidors; vol dir que no són cosa teva. No tries mida de màquina, no pedaces, no dimensiones: escrius una unitat de codi i la plataforma l'executa i l'escala.
El que es paga al pla de Consum són tres coses: el nombre d'execucions, el consum en gigabytes-segon (memòria assignada multiplicada pel temps d'execució) i el trànsit sortint. Hi ha una assignació gratuïta mensual generosa, i dues conseqüències pràctiques. La primera: una funció que no s'executa no costa res, i aquí hi ha l'estalvi davant del contenidor encès. La segona, menys intuïtiva: el cost és proporcional al temps d'execució, així que una funció lenta costa més, i una funció que espera bloquejada una crida HTTP externa et cobra per esperar.
- Desencadenadors i enllaços: el model mental
Aquí hi ha el concepte que cal interioritzar. Una funció té exactament un desencadenador —el que decideix quan s'executa— i zero o més enllaços d'entrada i de sortida, que són connexions declaratives a altres serveis. La plataforma s'encarrega de la connexió, l'autenticació, la deserialització i els reintents; tu reps objectes i retornes objectes.
| Desencadenador | Es dispara quan | Ús a Contoso |
|---|---|---|
| HTTP | Arriba una petició | API lleugera, webhooks de la passarel·la |
| Temporitzador | Es compleix una expressió cron | Purga nocturna de reserves caducades |
| Blob | Es crea o modifica un blob | Processar un fitxer carregat |
| Cua de Storage | Apareix un missatge | cola-emision-tarjetas |
| Service Bus | Arriba un missatge a cua o subscripció | Esdeveniments de reserva confirmada (06-05) |
| Event Grid | Es publica un esdeveniment | Blob nou a sttarjetascontosopro |
| Cosmos DB | Canvia un document (font de canvis) | Catàleg de tarifes |
La diferència que fa valuós el model són els enllaços. Compara:
// SENSE enllacos: lampisteria que cal escriure, provar i mantenir
var credencial = new DefaultAzureCredential();
var cliente = new BlobServiceClient(
new Uri("https://sttarjetascontosopro.blob.core.windows.net"), credencial);
var contenedor = cliente.GetBlobContainerClient("tarjetas-embarque");
await contenedor.CreateIfNotExistsAsync();
await contenedor.GetBlobClient(nombre).UploadAsync(flujo, overwrite: true);
// AMB enllac de sortida: es declara, i llestos
[BlobOutput("tarjetas-embarque/{nombre}.pdf", Connection = "AlmacenTarjetas")]
public byte[] Pdf { get; set; }Sis línies de lampisteria substituïdes per una declaració. I no és només brevetat: la connexió, els reintents i l'autenticació amb identitat administrada els gestiona el temps d'execució.
- Plans d'allotjament comparats
| Consum | Flex Consum | Premium | App Service | |
|---|---|---|---|---|
| Facturació | Per execució i GB-s | Per execució i GB-s | Instàncies sempre actives | Pla d'App Service |
| Arrencada en fred | Sí, notable | Reduïda; instàncies sempre llestes | No | No |
| Escalat màxim | 200 instàncies | Alt, configurable | 100 instàncies | Manual o automàtic |
| Integració amb xarxa virtual | No | Sí | Sí | Sí |
| Durada màxima | 5 min (fins a 10) | Configurable | Il·limitada | Il·limitada |
| Cost sense trànsit | Zero | Gairebé zero | Alt (instància mínima) | El del pla |
El que tria Contoso i per què:
GenerarTarjetaEmbarqueva en Flex Consum: necessita xarxa virtual per arribar ape-storage-tarjetasipe-sql-reservasper punt privat, cosa que el Consum clàssic no permet, i la seva càrrega és a ràfegues, amb consum gairebé zero de matinada.SincronizarTarifasva també en Flex Consum i a la mateixa aplicació: comparteix xarxa i configuració, i el seu volum és baix.- L'orquestració de la facturació en línia amb Durable Functions va en Premium. Les seves orquestracions duren hores —esperen que el passatger pugi un document—, i aquí l'arrencada en fred i el límit de durada importen.
- Res no va al pla d'App Service, llevat que volguessin reutilitzar
plan-contoso-api-proper aprofitar capacitat ja pagada.
- Crear el projecte i executar-lo en local
npm install -g azure-functions-core-tools@4 --unsafe-perm true # l host, a la teva maquina
func init ContosoFunciones --worker-runtime dotnet-isolated
cd ContosoFunciones
func new --name GenerarTarjetaEmbarque --template "Queue trigger"
func start # executa les funcions en local, amb depuracioEl model aïllat (dotnet-isolated) és el vigent: la funció corre en el seu propi procés, desacoblada de la versió de l'host. Els valors de configuració locals van a local.settings.json, que no es confirma mai al repositori —és al .gitignore per una raó—; a Azure, aquests mateixos noms es llegeixen de la configuració de l'aplicació.
GenerarTarjetaEmbarque: la funció de la cua
GenerarTarjetaEmbarque: la funció de la cuaQuan el passatger completa la facturació en línia, app-contoso-reservas-pro encua un missatge a cola-emision-tarjetas de stoperacionescontosopro. Aquesta funció el consumeix, genera el PDF i el deixa al contenidor tarjetas-embarque de sttarjetascontosopro.
public record SolicitudTarjeta(string Localizador, string NumeroVuelo,
string Pasajero, string Asiento, DateTime Salida);
public class GenerarTarjetaEmbarque
{
private readonly ILogger<GenerarTarjetaEmbarque> _reg;
private readonly IGeneradorPdf _pdf;
public GenerarTarjetaEmbarque(ILogger<GenerarTarjetaEmbarque> r, IGeneradorPdf p)
=> (_reg, _pdf) = (r, p);
[Function(nameof(GenerarTarjetaEmbarque))]
[BlobOutput("tarjetas-embarque/{Localizador}-{Asiento}.pdf", Connection = "AlmacenTarjetas")]
public async Task<byte[]> Run(
[QueueTrigger("cola-emision-tarjetas", Connection = "AlmacenOperaciones")]
SolicitudTarjeta solicitud,
FunctionContext contexto)
{
_reg.LogInformation("Emetent targeta {Loc} vol {Vuelo}",
solicitud.Localizador, solicitud.NumeroVuelo);
// Idempotencia: si el blob ja existeix, aquest missatge ja s ha processat (apartat 9)
if (await _pdf.YaExisteAsync(solicitud.Localizador, solicitud.Asiento))
{
_reg.LogInformation("Targeta {Loc} ja emesa; s omet", solicitud.Localizador);
return null; // retornar null NO escriu el blob
}
return await _pdf.GenerarAsync(solicitud);
}
}El que cal entendre d'aquest codi:
[QueueTrigger]declara el desencadenador. El temps d'execució sondeja la cua, deserialitza el JSON del missatge directament aSolicitudTarjetai te'l lliura tipat. Si la deserialització falla, el missatge va a la cua de missatges fallits sense executar el teu codi.Connection = "AlmacenOperaciones"no és una cadena de connexió: és el prefix d'un ajust de configuració. AmbAlmacenOperaciones__queueServiceUriapuntant al compte i la identitat administrada assignada, no hi ha cap clau. Aquest és el punt que més es fa malament.[BlobOutput]amb la plantilla{Localizador}-{Asiento}.pdf: els camps del missatge entrant s'interpolen a la ruta del blob. El nom del fitxer és determinista, i d'aquí surt de franc la comprovació d'idempotència.- Retornar
nullno escriu el blob, la manera neta de tallar sense llançar una excepció. I la injecció de dependències funciona com en qualsevol aplicació .NET: el constructor rep el registrador i el generador de PDF, cosa que fa la funció provable amb proves unitàries.
SincronizarTarifas: la font de canvis de Cosmos DB
SincronizarTarifas: la font de canvis de Cosmos DBQuan l'equip comercial actualitza una tarifa al contenidor tarifas de cosmos-contoso-tarifas-pro, la font de canvis que ja coneixes de 03-03 lliura el document modificat a aquesta funció, que refresca l'índex de cerca i avisa la memòria cau del motor de disponibilitat.
public class SincronizarTarifas
{
private readonly ILogger<SincronizarTarifas> _reg;
private readonly IIndiceTarifas _indice;
public SincronizarTarifas(ILogger<SincronizarTarifas> r, IIndiceTarifas i)
=> (_reg, _indice) = (r, i);
[Function(nameof(SincronizarTarifas))]
public async Task Run(
[CosmosDBTrigger(
databaseName: "catalogo",
containerName: "tarifas",
Connection = "CosmosTarifas",
LeaseContainerName = "arrendamientos",
CreateLeaseContainerIfNotExists = true)]
IReadOnlyList<Tarifa> cambios)
{
foreach (var tarifa in cambios)
{
// Upsert per clau: processar dues vegades deixa el mateix resultat
await _indice.UpsertAsync(tarifa);
_reg.LogInformation("Tarifa {Id} de {Ruta} sincronitzada",
tarifa.Id, tarifa.OrigenDestino);
}
}
}El contenidor d'arrendaments mereix atenció: és on el desencadenador desa fins on ha llegit cada partició. Viu a la mateixa base de dades, consumeix les seves pròpies RU/s i, si l'esborres, la funció reprocessa des del principi. La funció rep lots de canvis, no documents solts, i la clau de partició /origenDestino determina el paral·lelisme: cada partició es processa en ordre i de manera independent.
- Configuració, identitat administrada i Key Vault
# L aplicacio de funcions, en Flex Consum i integrada a la xarxa virtual
az functionapp create \
--resource-group rg-contoso-reservas-pro --name func-contoso-tarjetas-pro \
--storage-account stoperacionescontosopro --flexconsumption-location westeurope \
--runtime dotnet-isolated --runtime-version 8.0 --vnet vnet-contoso-pro --subnet snet-integracion-app \
--tags entorno=produccion proyecto=contoso-reservas \
centro-coste=CC-1042 [email protected]
# Identitat administrada assignada per l usuari, la de sempre
az functionapp identity assign -g rg-contoso-reservas-pro -n func-contoso-tarjetas-pro \
--identities $(az identity show -g rg-contoso-seguridad-pro \
-n id-contoso-api-pro --query id -o tsv)
# Connexions PER IDENTITAT: nom de servei, no clau
az functionapp config appsettings set -g rg-contoso-reservas-pro \
-n func-contoso-tarjetas-pro --settings \
"AlmacenOperaciones__queueServiceUri=https://stoperacionescontosopro.queue.core.windows.net" \
"AlmacenTarjetas__blobServiceUri=https://sttarjetascontosopro.blob.core.windows.net" \
"[email protected](SecretUri=https://kv-contoso-pro.vault.azure.net/secrets/clave-pasarela/)"Tres idees: les connexions amb el sufix __queueServiceUri / __blobServiceUri activen el mode per identitat, sense claus; la referència a Key Vault amb la sintaxi @Microsoft.KeyVault(...) de 04-03 resol el secret en temps d'execució i el valor no es veu mai al portal; i la identitat necessita els seus rols —Col·laborador de dades de la cua de Storage, Col·laborador de dades de Blob Storage i Usuari de secrets de Key Vault—.
- Durable Functions i el flux de facturació en línia
Les funcions normals són sense estat i de curta durada. I si el procés té diversos passos, triga hores i cal saber per on anava? Durable Functions hi afegeix estat durador i represa: un orquestrador descriu el flux amb codi normal, i la seva execució es persisteix automàticament a cada punt d'espera.
sequenceDiagram
participant P as Passatger
participant O as OrquestadorCheckIn
participant A as Activitats
P->>O: Inicia facturacio (localitzador)
O->>A: ValidarReserva
A-->>O: Reserva valida
par Fan-out
O->>A: ComprovarDocumentacio
O->>A: AssignarSeient
O->>A: CalcularEquipatge
end
A-->>O: Fan-in: resultats
O->>P: Demana foto del passaport
Note over O: Espera esdeveniment extern (fins a 24 h)
P-->>O: DocumentSubit
O->>A: EmetreTargeta -> cola-emision-tarjetas
Els tres patrons, aplicats:
- Encadenament de funcions:
ValidarReserva→EmitirTarjeta. Cada pas fa servir la sortida de l'anterior; si el procés cau al tercer pas, en reprendre no repeteix els dos primers. - Fan-out / fan-in: documentació, seient i equipatge són independents; es llancen en paral·lel i s'esperen totes. Redueix el temps total al del pas més lent.
- Esperar un esdeveniment extern: l'orquestrador s'atura a
WaitForExternalEvent("DocumentoSubido")amb un temps d'espera de 24 hores. Mentre espera no consumeix còmput ni factura; és el que fa inviable resoldre això amb una funció normal, limitada a minuts.
[Function(nameof(OrquestadorCheckIn))]
public static async Task<ResultadoCheckIn> Run(
[OrchestrationTrigger] TaskOrchestrationContext contexto)
{
var loc = contexto.GetInput<string>();
var reserva = await contexto.CallActivityAsync<Reserva>("ValidarReserva", loc);
// Fan-out: tres activitats en paral.lel
await Task.WhenAll( // ...i fan-in en esperar-les
contexto.CallActivityAsync<object>("ComprobarDocumentacion", reserva),
contexto.CallActivityAsync<object>("AsignarAsiento", reserva),
contexto.CallActivityAsync<object>("CalcularEquipaje", reserva));
// Espera humana: no consumeix computo mentrestant
using var cts = new CancellationTokenSource();
var evento = contexto.WaitForExternalEvent<string>("DocumentoSubido");
var plazo = contexto.CreateTimer(contexto.CurrentUtcDateTime.AddHours(24), cts.Token);
if (evento == await Task.WhenAny(evento, plazo)) cts.Cancel();
else return new ResultadoCheckIn(loc, "Caducado");
await contexto.CallActivityAsync("EmitirTarjeta", reserva);
return new ResultadoCheckIn(loc, "Completado");
}Regla d'or de l'orquestrador: el seu codi ha de ser determinista. Res de DateTime.Now, Guid.NewGuid() ni crides d'E/S directes, perquè l'orquestrador es reexecuta des del principi cada vegada que reprèn, reproduint el seu historial. Fes servir contexto.CurrentUtcDateTime i delega tot el que no és determinista en activitats.
- Idempotència, reintents, temps d'espera i límits
Aquesta és la lliçó que gairebé ningú no explica al principi i que tothom aprèn en producció: les cues garanteixen el lliurament almenys una vegada, no exactament una vegada. Si la funció cau després de generar el PDF però abans de confirmar el missatge, el missatge reapareix i la funció s'executa una altra vegada amb les mateixes dades. Sense protecció, el passatger rep dues targetes i el registre comptable queda desquadrat.
Com es protegeix, en ordre de preferència:
| Estratègia | Com | Aplicació a Contoso |
|---|---|---|
| Operació naturalment idempotent | Escriure amb clau determinista, upsert en lloc d'insert |
SincronizarTarifas: l'upsert per identificador |
| Comprovació prèvia | Veure si el resultat ja existeix abans de treballar | GenerarTarjetaEmbarque: el blob {Localizador}-{Asiento}.pdf |
| Registre de processats | Taula amb l'identificador del missatge | registroembarques de stoperacionescontosopro |
Sobre els reintents: la cua reintenta automàticament (cinc vegades per defecte) i després envia el missatge a la cua de missatges fallits. Un missatge que falla sempre —un JSON mal format, un vol inexistent— s'anomena missatge enverinat, i sense cua de missatges fallits bloquejaria la cua indefinidament. Vigila aquesta cua amb una alerta: si creix, alguna cosa està trencada.
Sobre temps d'espera i límits: 5 minuts per defecte a Consum (ampliable a 10), configurable a Flex i sense límit a Premium, amb el valor a functionTimeout de host.json. Un missatge de cua gran no hi cap (64 KB), així que envia referències, no càrregues: l'identificador del blob, no el PDF. I maxConcurrentCalls limita el paral·lelisme, que cal abaixar quan la funció escriu a db-reservas, perquè mil instàncies obrint connexions esgoten el grup de la base de dades.
- Proves, desplegament i supervisió
La lògica va en classes injectades —IGeneradorPdf, IIndiceTarifas—, així que es prova amb proves unitàries normals; la funció es limita a orquestrar. Per a la integració, func start amb l'emulador de Storage. El desplegament reutilitza la canalització de 05-04, amb ranures: es desplega a preproduccion, s'escalfa i s'intercanvia.
- task: AzureFunctionApp@2
inputs:
azureSubscription: sc-contoso-pro
appType: functionApp
appName: func-contoso-tarjetas-pro
deployToSlotOrASE: true
slotName: preproduccion
package: $(Pipeline.Workspace)/artefacto/funciones.zip
- task: AzureAppServiceManage@0 # i despres l intercanvi
inputs:
azureSubscription: sc-contoso-pro
Action: 'Swap Slots'
WebAppName: func-contoso-tarjetas-pro
SourceSlot: preproduccionApplication Insights ve integrat i és on es veu tot: execucions amb èxit i amb error, durada, telemetria de dependències i la traça d'extrem a extrem des de la cua fins al blob. La seva explotació és 07-03; aquí n'hi ha prou de saber que s'habilita en crear l'aplicació i que sense ell una funció que falla és una caixa negra.
- Quan NO fer servir funcions
- Processos de llarga durada amb estat en memòria: fes servir Durable Functions o un contenidor. I càrregues constants i altes: si el codi s'executa sense parar, un pla fix o Container Apps surt més barat que pagar per execució.
- Latència mínima garantida a la primera petició: l'arrencada en fred del pla de Consum no és acceptable per a la ruta de compra.
- Aplicacions amb molta lògica compartida i desplegament conjunt: si les «funcions» són un monòlit trossejat que sempre es desplega junt, és una API, i el seu lloc és App Service o Container Apps. El mateix amb connexions persistents o dependències pesades d'arrencada: cada instància nova paga aquesta arrencada, i amb escalat agressiu la destinació pateix.
Errors Comuns i Consells
- No fer la funció idempotent. Es manifesta com a duplicats esporàdics impossibles de reproduir. Dissenya-ho des del primer dia.
- Fer servir cadenes de connexió amb clau als ajustos de
Connection. Fes servir el sufix__blobServiceUriamb identitat administrada. - Ficar la càrrega completa al missatge. Límit de 64 KB a cues de Storage: envia la referència.
- Escriure codi no determinista en un orquestrador.
DateTime.NowoGuid.NewGuid()produeixen resultats incoherents en reprendre. - Ignorar la cua de missatges fallits, on acaben els missatges enverinats; si ningú no la mira, els errors són invisibles. I no limitar la concurrència quan la funció escriu a
db-reservas: mil instàncies esgoten el grup de connexions. - Confirmar
local.settings.json. Conté credencials locals. Comprova-ho a la revisió de 05-02. - Consell: mesura la durada a Application Insights; abaixar una funció de 4 s a 1,5 s redueix la factura de Consum gairebé en la mateixa proporció. I una funció, una responsabilitat: si té tres desencadenadors lògics diferents, són tres funcions.
Exercicis
Exercici 1. Contoso Millas necessita una funció que, quan un passatger completa un vol, sumi les milles corresponents al seu perfil a cosmos-contoso-tarifas-pro. Els esdeveniments arriben per cola-vuelos-completados.
- Tria desencadenador, enllaços i pla d'allotjament, i justifica-ho.
- El primer dia en producció, alguns passatgers apareixen amb les milles duplicades. Explica'n la causa exacta, dona dues maneres d'arreglar-ho, i indica les etiquetes del recurs i l'alerta que configuraries des del dia u.
Exercici 2. Dissenya amb Durable Functions el procés de reemborsament d'un bitllet: validar la sol·licitud, comprovar en paral·lel penalització i saldo de la passarel·la, esperar l'aprovació d'un supervisor (màxim 72 hores) i, si s'aprova, executar l'abonament i notificar.
- Indica quin patró cobreix cada tram i per què no es pot resoldre amb una funció normal al pla de Consum.
- Escriu en pseudocodi l'espera del supervisor amb la seva caducitat i digues què passa si l'orquestrador es reinicia mentre espera.
Exercici 3. Una funció amb desencadenador HTTP consulta db-reservas i respon en 200 ms quan hi ha poc trànsit, però en obrir la venda de places retorna errors de temps d'espera de la base de dades.
- Explica el mecanisme de la fallada.
- Proposa tres mesures correctores.
Solucions
Solució 1:
- Desencadenador de cua de Storage sobre
cola-vuelos-completados, amb enllaç de sortida a Cosmos DB al contenidorperfiles. Pla Flex Consum: volum a ràfegues concentrades en aterrar els vols, cost gairebé zero de matinada, i necessita xarxa virtual per arribar al punt privat de Cosmos. - La causa és el lliurament almenys una vegada: si la funció suma les milles i cau abans de confirmar el missatge, aquest reapareix i es torna a sumar. Sumar és l'operació no idempotent per excel·lència. Arranjament (a): desar al document del perfil el conjunt d'identificadors de vol ja acreditats i descartar l'esdeveniment si ja hi és —comprovació prèvia dins de la mateixa escriptura—. Arranjament (b): registrar l'identificador del missatge a la taula
registroembarquesabans de sumar, i descartar si ja existeix. La (a) és preferible perquè no hi afegeix un altre magatzem ni una altra finestra de fallada. Etiquetes:entorno,proyecto=contoso-millas,centro-coste=CC-2077ipropietario. L'alerta del primer dia és sobre la longitud de la cua de missatges fallits: tan bon punt creix, hi ha missatges enverinats i passatgers sense les seves milles.
Solució 2:
- Validar → comprovar → abonar → notificar és encadenament; penalització i saldo en paral·lel són fan-out / fan-in; l'aprovació del supervisor és esperar un esdeveniment extern. No cap en una funció normal perquè l'espera dura fins a 72 hores i el pla de Consum talla als 5 o 10 minuts; a més caldria persistir el punt exacte del procés, i una funció normal és sense estat.
var evento = contexto.WaitForExternalEvent<Decision>("AprobacionSupervisor");juntament ambvar plazo = contexto.CreateTimer(contexto.CurrentUtcDateTime.AddHours(72), cts.Token);i unTask.WhenAnysobre tots dos; si guanya el termini es rebutja per caducitat, i si guanya l'esdeveniment es cancel·la el temporitzador. Si l'orquestrador es reinicia mentre espera, no passa res: la instància no està ocupant còmput, el seu historial està persistit i en reprendre es reprodueix fins al punt d'espera. Aquesta és exactament la propietat que aporta el model durador.
Solució 3:
- La funció escala a desenes o centenars d'instàncies en paral·lel, i cada instància obre les seves pròpies connexions a
db-reservas. El grup de connexions del servidor s'esgota, les peticions s'encuen i acaben expirant. El símptoma apareix a la base de dades, però la causa és l'escalat descontrolat de la funció. - (a) Limitar la concurrència a
host.jsoni fixarfunctionAppScaleLimita un sostre compatible amb la base de dades. (b) Reutilitzar el client de base de dades com a estàtic o singleton en lloc de crear-ne un per invocació, perquè les connexions s'agrupin. (c) Treure la sincronia del camí: encuar la petició i respondre immediatament, o posar una memòria cau al davant per a les consultes repetides. Com a reforç, revisar el nivell desql-contoso-reservas-pro(03-02), tot i que escalar la base de dades sense arreglar la concurrència només mou el límit.
Conclusió
Ja saps què vol dir de debò «sense servidor»: no hi ha màquina a triar ni a pedaçar, es paga per execucions i gigabytes-segon, una funció aturada costa zero i una funció lenta costa més. Tens interioritzat el model mental de desencadenadors i enllaços —un desencadenador que decideix quan, enllaços d'entrada i sortida que eliminen la lampisteria de connectar-se, autenticar-se i reintentar— i coneixes els més usats amb el seu encaix a Contoso. Saps comparar els plans d'allotjament per arrencada en fred, escalat, xarxa virtual, durada i cost, i per què les funcions de Contoso van en Flex Consum mentre l'orquestració de la facturació en línia necessita Premium.
Has escrit les dues funcions reals: GenerarTarjetaEmbarque, disparada per cola-emision-tarjetas, amb enllaç de sortida al contenidor tarjetas-embarque mitjançant una plantilla de nom determinista que regala la idempotència; i SincronizarTarifas, alimentada per la font de canvis de cosmos-contoso-tarifas-pro amb el seu contenidor d'arrendaments i el seu processament per lots. Les has configurat amb connexions per identitat (__blobServiceUri, __queueServiceUri) i referències a kv-contoso-pro, sense ni una sola clau. Amb Durable Functions has orquestrat la facturació en línia aplicant encadenament, fan-out/fan-in i espera d'esdeveniment extern durant 24 hores sense consumir còmput, respectant la regla de l'orquestrador determinista. I t'endus la lliçó dura: almenys una vegada, no exactament una vegada, amb les seves tres estratègies d'idempotència, la cua de missatges fallits que cal vigilar, els temps d'espera, el límit de 64 KB i la concurrència que cal frenar quan al darrere hi ha una base de dades. Saps desplegar amb ranures des de la canalització, supervisar amb Application Insights (07-03) i, sobretot, quan no fer servir funcions.
Queda una peça incòmoda. Quan un vol es retarda, Contoso ha de buscar els passatgers afectats a db-reservas, avisar-los per correu i per missatge, publicar al canal de l'equip d'operacions i obrir una incidència al sistema de suport. Res d'això no és lògica de negoci complexa: és enganxar sistemes entre si, i escriure-ho com a codi significa mantenir a mà quatre integracions amb les seves autenticacions, els seus reintents i els seus formats. A més, qui coneix aquest procés no és en Diego, és l'equip d'operacions, que no programa. La lliçó següent, Azure Logic Apps, és exactament per a això: fluxos de treball visuals sobre un catàleg de més de mil connectors, amb la seva definició en JSON versionable, el seu control de flux, la seva gestió d'errors i el seu historial d'execucions, i amb el criteri per saber quan toca una aplicació lògica, quan una funció i quan Data Factory.
Curs d'Azure
Mòdul 1: Introducció a Azure
- Què és Azure?
- Models de servei, regions i zones de disponibilitat
- Crear i configurar el teu compte d'Azure
- Recorregut pel portal d'Azure
- Azure Resource Manager: subscripcions, grups de recursos i etiquetes
- Azure CLI, PowerShell i Cloud Shell
Mòdul 2: Serveis principals d'Azure
- Màquines virtuals d'Azure
- Escalat i alta disponibilitat del còmput
- Azure App Service
- Azure Storage: blobs, fitxers, cues i taules
- Xarxes a Azure: xarxes virtuals, subxarxes i NSG
- Connectivitat híbrida i lliurament global
Mòdul 3: Bases de dades d'Azure
- Triar el servei de dades adequat
- Azure SQL Database
- Azure Cosmos DB
- Azure Database for MySQL
- Azure Database for PostgreSQL
- Analítica de dades: Data Lake, Data Factory i Synapse
Mòdul 4: Seguretat a Azure
- Microsoft Entra ID i gestió d'identitats
- RBAC i identitats administrades
- Azure Key Vault
- Protecció DDoS i tallafoc d'aplicacions web
- Microsoft Defender for Cloud
- Governança i compliment amb Azure Policy
Mòdul 5: Azure DevOps
- Introducció a Azure DevOps
- Azure Repos
- Azure Pipelines: integració contínua
- Desplegament continu amb entorns i aprovacions
- Azure Artifacts
- Infraestructura com a codi amb Bicep
Mòdul 6: Serveis avançats d'Azure
- Contenidors a Azure: Container Registry i Container Apps
- Azure Kubernetes Service (AKS)
- Azure Functions
- Azure Logic Apps
- Missatgeria i esdeveniments: Service Bus, Event Grid i Event Hubs
- Serveis d'IA d'Azure
Mòdul 7: Monitoratge i gestió
- Azure Monitor: mètriques, alertes i taulers
- Log Analytics i consultes KQL
- Application Insights
- Azure Automation i runbooks
- Còpies de seguretat i recuperació davant desastres
Mòdul 8: Gestió i optimització de costos
- Calculadora de preus i estimació de costos
- Azure Cost Management: anàlisi, pressupostos i alertes
- Reserves, plans d'estalvi i Azure Hybrid Benefit
- Azure Advisor
- Estratègies d'optimització i cultura FinOps
