Avui, quan un passatger prem «Confirmar reserva» a app-contoso-reservas-pro, dins d'aquella única petició HTTP passen sis coses seguides: es cobra a la passarel·la, s'actualitza la disponibilitat, s'encua l'emissió de la targeta, s'acrediten les milles, s'avisa el sistema de facturació i s'envia el correu de confirmació. Tot síncron, tot en línia. La conseqüència és brutal i Contoso Airlines ja l'ha patida: si el servei de milles va lent, la compra falla. Un component accessori tomba l'ingrés principal de la companyia.
Aquesta lliçó resol aquest problema d'arrel amb desacoblament: els components deixen de cridar-se els uns als altres i passen a intercanviar missatges i esdeveniments a través d'una infraestructura intermèdia. Veuràs els tres serveis que Azure ofereix per a això, quan fer servir cadascun, i les conseqüències de disseny que porta aquest model, que no són de franc.
Contingut
- Per què desacoblar
- Missatge davant d'esdeveniment
- Els tres serveis comparats
- Azure Service Bus
- Azure Event Grid
- Azure Event Hubs
- El flux complet de Contoso
- Lliurament almenys una vegada, ordenació i idempotència
- Cost de cada servei
- Errors Comuns i Consells
- Exercicis
- Conclusió
- Per què desacoblar
Encadenar sis crides síncrones té tres defectes acumulatius. La disponibilitat es multiplica: si cada component té un 99,9 %, la cadena de sis baixa al 99,4 %, més de quatre hores de caiguda al mes. La latència se suma: el passatger espera el que triguen tots. I l'acoblament es congela: afegir un setè pas obliga a tocar i redesplegar el codi de la compra.
Amb un intermediari, la compra fa l'imprescindible —cobrar i reservar la plaça— i publica un fet. Els altres reaccionen al seu ritme. Si el servei de milles està caigut, el seu missatge espera a la cua i es processa quan torna; el passatger ni se n'assabenta. Això és el desacoblament: en el temps, en l'espai i en la disponibilitat.
- Missatge davant d'esdeveniment
Aquesta distinció és la que gairebé tothom confon, i d'ella depèn triar bé el servei.
| Missatge | Esdeveniment | |
|---|---|---|
| Què expressa | Una instrucció: fes això | Un fet: això ha passat |
| Intenció de l'emissor | Espera que algú el processi | No sap ni li importa qui hi reacciona |
| Contingut | La càrrega completa que cal | Lleuger: què ha passat, quan i sobre què |
| Acoblament | L'emissor coneix el destinatari | Cap |
| Si ningú no el consumeix | És un error: es queda a la cua | És normal: es descarta |
| Exemple a Contoso | «Emet la targeta del localitzador XR7742» | «La reserva XR7742 s'ha confirmat» |
La regla mnemotècnica: un missatge té destinatari i intenció; un esdeveniment té emissor i passat. La forma verbal ho delata —EmitirTarjeta davant de ReservaConfirmada— i no és cosmètic: el missatge va a Service Bus perquè algú ha de processar-lo i no es pot perdre; l'esdeveniment va a Event Grid perquè zero, un o set subscriptors s'hi poden interessar i l'emissor continua igual.
- Els tres serveis comparats
| Service Bus | Event Grid | Event Hubs | |
|---|---|---|---|
| Per a què | Missatgeria empresarial fiable | Distribució d'esdeveniments discrets | Ingesta massiva de telemetria |
| Unitat | Missatge (fins a 256 KB / 100 MB) | Esdeveniment (64 KB) | Registre (petit, en flux) |
| Volum típic | Milers per segon | Milions per segon | Milions per segon, sostinguts |
| Model de lliurament | El consumidor extreu | El servei empeny | El consumidor llegeix per desplaçament |
| Ordre | Sí, amb sessions | No garantit | Sí, dins de la partició |
| Reintents i missatges fallits | Complets | Sí, amb reintents i cua | El consumidor gestiona la seva posició |
| Retenció | Fins que es consumeix | 24 hores de reintents | Finestra de temps (1-7 dies o més) |
| Cas a Contoso | reservas-confirmadas |
ReservaConfirmada, blob nou |
Telemetria de taulells |
I no oblidis les cues d'Azure Storage de 02-04: simples, molt barates, sense temes ni sessions ni transaccions, amb missatges de 64 KB i set dies de retenció. N'hi ha prou quan hi ha un sol consumidor, l'ordre és indiferent i no necessites filtres ni lliurament transaccional. cola-emision-tarjetas és exactament aquest cas i per això continua sent una cua de Storage. Tan bon punt necessitis temes, sessions, detecció de duplicats o transaccions, és Service Bus.
- Azure Service Bus
az servicebus namespace create -g rg-contoso-reservas-pro -n sb-contoso-pro \
--location westeurope --sku Premium --capacity 1 \
--tags entorno=produccion proyecto=contoso-reservas \
centro-coste=CC-1042 [email protected]
# Un TEMA: un publicador, diversos interessats amb criteris diferents
az servicebus topic create -g rg-contoso-reservas-pro --namespace-name sb-contoso-pro \
-n reservas-confirmadas --max-size 5120 --enable-duplicate-detection true
az servicebus topic subscription create -g rg-contoso-reservas-pro \
--namespace-name sb-contoso-pro --topic-name reservas-confirmadas \
-n tarjetas --max-delivery-count 5 --dead-lettering-on-message-expiration true
# Filtre: fidelitzacio nomes vol les reserves de socis
az servicebus topic subscription rule create -g rg-contoso-reservas-pro \
--namespace-name sb-contoso-pro --topic-name reservas-confirmadas \
--subscription-name fidelizacion -n solo-socios \
--filter-sql-expression "esSocio = true AND importe > 0"Les peces que cal conèixer:
- Cua davant de tema. Una cua és punt a punt: cada missatge el processa un consumidor. Un tema és publicació i subscripció: cada subscripció rep la seva pròpia còpia. Contoso fa servir un tema amb les subscripcions
tarjetas,facturacionifidelizacion, de manera que afegir un quart interessat no toca l'emissor. - Filtres de subscripció. Regles SQL sobre les propietats del missatge.
fidelizacionnomés rep reserves de socis, així que no veu el que no li pertoca: menys procés i menys cost. - Sessions. Sense elles no hi ha ordre garantit. Amb
SessionId—per exemple, el localitzador— tots els missatges d'aquella sessió els processa un sol consumidor i en ordre. És el que permet garantir que «reserva creada» es processi abans que «reserva modificada». - Bloqueig amb ullada. El mode de recepció correcte: el consumidor bloqueja el missatge sense esborrar-lo, treballa, i només llavors el completa. Si el procés mor, el bloqueig caduca i el missatge torna a estar disponible. El mode alternatiu, rebre i esborrar, perd missatges davant de qualsevol fallada.
- Ajornament. Apartar un missatge que encara no es pot processar —falta una dada que arribarà després— sense bloquejar la cua, per recuperar-lo més tard pel seu número de seqüència.
- Cua de missatges amb problemes de lliurament. La peça que salva els equips. Després de
max-delivery-countintents fallits, el missatge es mou a una subcua en lloc de bloquejar el procés per sempre. Allà s'inspecciona, es corregeix i es reenvia. Sense ella, un missatge enverinat embussa la cua indefinidament. - Transaccions i detecció de duplicats. Es poden agrupar diverses operacions —completar un missatge i publicar-ne un altre— en una unitat atòmica dins del mateix espai de noms. I amb la detecció de duplicats activada, el servei descarta durant una finestra de temps els missatges amb el mateix
MessageId.
| Nivell | Quan |
|---|---|
| Bàsic | Només cues. Ni temes ni sessions: gairebé mai no serveix |
| Estàndard | Temes, sessions, transaccions. Capacitat compartida i variable |
| Premium | Recursos dedicats, rendiment predictible, punts privats. Producció |
Emissió i consum, amb identitat administrada i sense cadenes de connexió:
// Publicar: el fet porta propietats perque els filtres puguin actuar
var cliente = new ServiceBusClient("sb-contoso-pro.servicebus.windows.net",
new DefaultAzureCredential());
var emisor = cliente.CreateSender("reservas-confirmadas");
var mensaje = new ServiceBusMessage(BinaryData.FromObjectAsJson(reserva))
{
MessageId = reserva.Localizador, // deteccio de duplicats
SessionId = reserva.Localizador, // ordre per reserva
ContentType = "application/json"
};
mensaje.ApplicationProperties["esSocio"] = reserva.EsSocio; // fet servir pel filtre
mensaje.ApplicationProperties["importe"] = reserva.Importe;
await emisor.SendMessageAsync(mensaje);
// Consumir amb bloqueig amb ullada: es completa NOMES si la feina ha acabat be
var procesador = cliente.CreateProcessor("reservas-confirmadas", "tarjetas",
new ServiceBusProcessorOptions { MaxConcurrentCalls = 10, AutoCompleteMessages = false });
procesador.ProcessMessageAsync += async args =>
{
var reserva = args.Message.Body.ToObjectFromJson<Reserva>();
try
{
await _emisorTarjetas.EmitirAsync(reserva); // idempotent (06-03)
await args.CompleteMessageAsync(args.Message);
}
catch (DatoInvalidoException ex)
{
// Error permanent: no te sentit reintentar, va directe a la subcua
await args.DeadLetterMessageAsync(args.Message, "DatoInvalido", ex.Message);
}
// Qualsevol altra excepcio: no es completa, el bloqueig caduca i es reintenta
};
await procesador.StartProcessingAsync();Fixa't en la distinció del catch: davant d'un error permanent s'envia a la subcua immediatament, perquè reintentar cinc vegades una dada mal formada només gasta temps; davant d'un error transitori es deixa que el bloqueig caduqui i el missatge es reintenti sol.
- Azure Event Grid
Event Grid és un encaminador d'esdeveniments amb publicació i subscripció per enviament: el servei empeny l'esdeveniment a la destinació i gestiona els reintents. No cal sondejar res.
- Temes del sistema: els mateixos serveis d'Azure publiquen esdeveniments sense configuració. Un blob nou a
sttarjetascontosoproemetMicrosoft.Storage.BlobCreated, i Contoso ho fa servir per disparar la indexació de la targeta acabada de generar. El mateix amb Key Vault avisant d'un certificat a punt de caducar, o amb ACR avisant d'una imatge nova. - Temes personalitzats: els publiques tu, i aquí hi va
ReservaConfirmada. - Esquema CloudEvents: l'estàndard de la CNCF, i el recomanat avui davant de l'esquema propi d'Event Grid, perquè fa els esdeveniments portables.
- Filtres: per tipus d'esdeveniment, per prefix o sufix del subjecte i per valors de propietats avançades. El filtratge passa al servei, així que el subscriptor només rep el que li interessa.
- Reintents i cua d'esdeveniments fallits: si la destinació no respon, reintenta amb espera exponencial durant 24 hores i després diposita l'esdeveniment en un compte d'emmagatzematge configurat. Si no el configures, l'esdeveniment es perd en silenci, que és el parany més comú del servei.
az eventgrid topic create -g rg-contoso-reservas-pro -n evgt-contoso-reservas-pro \
--location westeurope --input-schema cloudeventschemav1_0
az eventgrid event-subscription create --name sub-motor-disponibilidad \
--source-resource-id $(az eventgrid topic show -g rg-contoso-reservas-pro \
-n evgt-contoso-reservas-pro --query id -o tsv) \
--endpoint-type azurefunction \
--endpoint "<id de la funcio>" \
--included-event-types Contoso.Reservas.ReservaConfirmada \
--advanced-filter data.importe NumberGreaterThan 500 \
--deadletter-endpoint "<id del contenidor d esdeveniments fallits>"L'esdeveniment en CloudEvents, mostrant l'essencial: és lleuger i descriu un fet, no porta la reserva sencera.
{
"specversion": "1.0",
"type": "Contoso.Reservas.ReservaConfirmada",
"source": "/contoso/reservas/app-contoso-reservas-pro",
"id": "b41f7c22-9e0a-4a11-9a3c-7d2f5c1e8a90",
"subject": "reservas/XR7742",
"time": "2026-08-15T09:14:22Z",
"datacontenttype": "application/json",
"data": { "localizador": "XR7742", "vuelo": "CA-1187",
"origenDestino": "BCN-CDG", "importe": 214.50, "esSocio": true }
}type permet filtrar per classe d'esdeveniment, subject per recurs concret —amb filtres de prefix com reservas/XR—, i id és l'identificador que el consumidor fa servir per detectar duplicats.
- Azure Event Hubs
Event Hubs no és per a esdeveniments de negoci sinó per a fluxos de dades a gran escala: telemetria, registres, sèries temporals. Contoso el fa servir per als taulells de facturació, que emeten sense parar l'estat de la cua de passatgers, el temps d'atenció i les incidències d'equipatge.
- Particions: el flux es divideix en particions que es llegeixen en paral·lel. L'ordre es garanteix dins d'una partició, així que la clau de partició —l'identificador del taulell— determina què queda ordenat. El nombre de particions fixa el paral·lelisme màxim i convé pensar-ho en crear el recurs.
- Grups de consumidors: cada aplicació consumidora té la seva pròpia vista del flux amb el seu propi avanç. El tauler en temps real i el procés analític llegeixen les mateixes dades sense destorbar-se.
- Retenció: els registres no s'esborren en llegir-se; romanen una finestra de temps, d'1 a 7 dies a Estàndard i més a Premium. Això permet reprocessar tornant enrere en el desplaçament, cosa impossible amb una cua.
- Captura: escriu automàticament el flux en Avro sobre
stlagocontosopro, a la capabroncedel Data Lake (03-06), sense escriure ni una línia de codi. Aquesta és la integració clau amb l'analítica. - Compatibilitat amb Kafka: un productor o consumidor de Kafka apunta a Event Hubs canviant la configuració de connexió, sense tocar el codi. És la via de migració sense operar un clúster.
az eventhubs namespace create -g rg-contoso-reservas-pro -n evhns-contoso-telemetria-pro \
--location westeurope --sku Standard --capacity 2 --enable-auto-inflate --maximum-throughput-units 10
az eventhubs eventhub create -g rg-contoso-reservas-pro \
--namespace-name evhns-contoso-telemetria-pro -n facturacion-mostradores \
--partition-count 8 --retention-time-in-hours 72 \
--enable-capture true --capture-interval 300 \
--destination-name EventHubArchive.AzureBlockBlob \
--storage-account stlagocontosopro --blob-container bronce--enable-auto-inflate puja les unitats de rendiment automàticament davant d'un pic —i aquí va l'avís de cost: pugen soles, però no baixen soles, així que un pic puntual deixa el recurs facturant al màxim fins que algú l'ajusta—.
- El flux complet de Contoso
graph LR WEB["app-contoso-reservas-pro<br/>Confirmar reserva"] -->|1 missatge| SB["Service Bus<br/>tema reservas-confirmadas"] WEB -->|2 esdeveniment| EG["Event Grid<br/>evgt-contoso-reservas-pro"] SB --> S1["Subscripcio tarjetas"] --> F1["Function<br/>GenerarTarjetaEmbarque"] SB --> S2["Subscripcio facturacion"] --> CA["ca-motor-facturacion"] SB --> S3["Subscripcio fidelizacion<br/>filtre esSocio = true"] --> F2["Function<br/>AcreditarMillas"] F1 --> BLOB["sttarjetascontosopro<br/>tarjetas-embarque"] BLOB -->|BlobCreated| EG2["Event Grid<br/>tema del sistema"] --> LA["Logic App:<br/>notificar el passatger"] EG --> ML["Model de demanda"] MOS["Taulells de facturacio"] -->|telemetria| EH["Event Hubs<br/>facturacion-mostradores"] EH -->|captura| LAGO["stlagocontosopro / bronce"] EH --> PANEL["Tauler d operacions<br/>en temps real"] SB -.->|fallades| DLQ["Cua de missatges<br/>amb problemes de lliurament"]
Llegeix-ho com una decisió de disseny a cada fletxa. La confirmació publica un missatge al tema, perquè emetre la targeta, facturar i acreditar milles han de passar i no es poden perdre; i publica un esdeveniment a Event Grid, perquè hi pot haver interessats que avui no existeixen —el model de predicció de demanda n'és un— sense que l'emissor els conegui. Quan la funció deixa el PDF al contenidor, el tema del sistema de Storage emet BlobCreated i una aplicació lògica (06-04) notifica el passatger: ningú no ha hagut de programar aquesta connexió. La telemetria dels taulells va per Event Hubs, amb captura automàtica cap al Data Lake i lectura simultània del tauler en temps real des d'un altre grup de consumidors. I la petició del passatger acaba tan bon punt es cobra i es reserva la plaça: si fidelització està caiguda, el seu missatge espera a la subscripció i la compra ni se n'assabenta. Aquest era el problema del principi, i està resolt.
- Lliurament almenys una vegada, ordenació i idempotència
Aquestes són les tres conseqüències inevitables del model, i convé acceptar-les com a part del disseny i no com a sorpreses.
Lliurament almenys una vegada. Els tres serveis garanteixen que el missatge arriba, no que arriba una sola vegada. Un consumidor pot rebre un duplicat si cau després de processar i abans de completar, si el bloqueig caduca per trigar massa, o si l'emissor reintenta en no rebre la confirmació. El lliurament exactament una vegada d'extrem a extrem no existeix en un sistema distribuït; el que existeix és processament idempotent, que el fa innecessari.
Ordenació. Per defecte no hi ha ordre global. S'aconsegueix ordre per sessió a Service Bus i per partició a Event Hubs, i Event Grid no ho garanteix de cap manera. Dissenya perquè l'ordre no importi sempre que puguis —incloent-hi una marca de temps o un número de versió a la càrrega i descartant el que és vell—, i reserva les sessions per als casos en què de debò calgui, perquè limiten el paral·lelisme.
Idempotència, ja vista a 06-03 i ara obligatòria en tot consumidor. Les tres eines: MessageId amb detecció de duplicats a Service Bus, que resol la finestra curta; l'identificador d'esdeveniment registrat pel consumidor, amb la taula registroembarques de stoperacionescontosopro; i les operacions naturalment idempotents, escriure amb clau determinista o upsert en lloc d'insert. Aquesta última és sempre la millor perquè no necessita infraestructura addicional.
- Cost de cada servei
| Servei | Com es factura | Què dispara la factura |
|---|---|---|
| Cues de Storage | Per transacció i emmagatzematge | Gairebé res; és l'opció més barata |
| Service Bus Estàndard | Per operació, amb base mensual | El sondeig agressiu: cada intent de recepció buit és una operació |
| Service Bus Premium | Per unitat de missatgeria i hora | Dimensionar de més «per si de cas» |
| Event Grid | Per operació (milió d'operacions) | Subscripcions sense filtrar que ho reben tot |
| Event Hubs | Per unitat de rendiment i hora + esdeveniments | L'escalat automàtic que puja i no baixa, i la captura |
Tres consells concrets: fes servir recepció amb espera llarga a Service Bus en lloc de sondejar en bucle, perquè una recepció buida cada segon són 2,6 milions d'operacions al mes per consumidor; filtra al servei, no al consumidor, perquè el que es filtra a Event Grid no es factura com a lliurament; i revisa les unitats de rendiment d'Event Hubs després de cada pic, perquè auto-inflate puja però no baixa. En desenvolupament, elimina els espais de noms que no es facin servir: un Service Bus Premium o un Event Hubs amb unitats reservades facturen tant si són buits com plens.
Errors Comuns i Consells
- Fer servir Event Hubs per a missatgeria de negoci. No té bloqueig per missatge ni cua de missatges fallits: la gestió de fallades és teva i acabaràs reimplementant Service Bus malament.
- No configurar la cua de missatges amb problemes de lliurament a Service Bus ni la destinació d'esdeveniments fallits a Event Grid. Les fallades esdevenen invisibles i les dades es perden.
- Ficar la càrrega completa a l'esdeveniment. Un esdeveniment descriu un fet i porta una referència; si necessites enviar 5 MB, puja-ho a
sttarjetascontosoproi envia'n l'URI. - Assumir ordre on no n'hi ha. Si l'ordre és imprescindible, sessions o particions; si no, marca de versió a la càrrega.
- No fer idempotent el consumidor. Duplicats esporàdics, irreproduïbles i sempre en producció.
- Reintentar indefinidament un error permanent. Distingeix el transitori del permanent i envia el segon a la subcua immediatament.
- Sondejar en bucle tancat. Dispara la factura d'operacions. Recepció amb espera llarga.
- Consell: posa nom de fet en passat als esdeveniments (
ReservaConfirmada) i d'instrucció als missatges (EmitirTarjeta). El nom obliga a decidir quin és quin, i amb això el servei es tria sol. - Consell: versiona l'esquema des del primer esdeveniment, amb
Contoso.Reservas.ReservaConfirmada.v1. El dia que canviï la càrrega, els consumidors antics continuaran funcionant.
Exercicis
Exercici 1. Contoso Millas vol que, en completar-se un vol, s'acreditin les milles al soci, es recalculi el seu nivell i s'enviï un resum mensual; a més, l'equip de dades vol tots els esdeveniments de vol completat per al seu model de predicció, i els torns d'embarcament emeten 400 lectures per segon que cal arxivar i visualitzar en directe.
- Assigna cada necessitat a un servei i justifica l'elecció amb la distinció missatge/esdeveniment.
- Dissenya el tema, les subscripcions i els seus filtres per a la part de Service Bus.
- Indica les etiquetes obligatòries i una mesura d'estalvi per a l'entorn de desenvolupament.
Exercici 2. La subscripció facturacion acumula 12.000 missatges a la seva cua de missatges amb problemes de lliurament. En inspeccionar-los, tots són del mateix dia i tenen DeadLetterReason: MaxDeliveryCountExceeded.
- Què va passar i per què la cua principal va continuar funcionant?
- Descriu el procediment per recuperar-los, indicant què cal verificar abans de reenviar.
- Proposa dues mesures perquè no torni a passar i una alerta.
Exercici 3. Un consumidor de reservas-confirmadas triga uns 8 minuts a processar cada missatge perquè crida un sistema extern lent. El bloqueig de Service Bus és de 5 minuts. Explica què està passant, què es veu en producció i dona dues solucions de naturalesa diferent.
Solucions
Solució 1:
- Acreditar milles i recalcular el nivell són missatges: són instruccions que s'han d'executar i no es poden perdre, així que Service Bus. L'avís a l'equip de dades és un esdeveniment —«vol completat», un fet al qual se subscriu qui vulgui, i demà potser altres— així que Event Grid. Les 400 lectures per segon dels torns són telemetria d'alt volum que cal arxivar i veure en directe: Event Hubs amb captura al Data Lake i un segon grup de consumidors per al tauler.
- Tema
vuelos-completadosasb-contoso-pro, amb la subscripciómillassense filtre i la subscripciónivel-fidelidadamb el filtreesSocio = true AND millasAcreditadas > 0. Totes dues ambmax-delivery-count 5i enviament a la subcua activat. El resum mensual no és una subscripció: és un procés programat, i ficar-lo aquí seria confondre missatgeria amb planificació. entorno,proyecto=contoso-millas,centro-coste=CC-2077ipropietario. Estalvi en desenvolupament: nivell Estàndard en lloc de Premium per a Service Bus, una sola unitat de rendiment sense auto-inflate a Event Hubs amb retenció de 24 hores, i eliminar els espais de noms quan no es facin servir, perquè facturen encara que estiguin buits.
Solució 2:
- El consumidor de facturació va fallar de manera sistemàtica durant aquell dia —un desplegament amb un error, o el sistema de facturació caigut—. Cada missatge es va reintentar 5 vegades i, en superar
max-delivery-count, Service Bus el va moure automàticament a la subcua. Justament per això la cua principal va continuar funcionant: sense aquest mecanisme, el primer missatge enverinat hauria bloquejat el procés i la resta de subscripcions també se n'haurien vist afectades. La subcua va fer exactament la seva feina. - Abans de reenviar res, cal verificar tres coses: que la causa arrel està corregida i desplegada, que el consumidor és idempotent —perquè part d'aquests missatges poden haver-se processat parcialment— i què diuen
DeadLetterReasoniDeadLetterErrorDescriptiond'una mostra representativa, per si hi ha més d'una causa barrejada. Després es llegeixen els missatges de la subcua i es reenvien al tema en lots controlats, vigilant la cua principal per no repetir l'embús. - Mesures: (a) distingir al codi els errors permanents dels transitoris i enviar els primers a la subcua immediatament, sense esgotar cinc intents; (b) un interruptor que pausi el consumidor quan la taxa de fallades supera un llindar, perquè els missatges esperin a la cua en lloc de cremar els seus reintents contra un sistema caigut. L'alerta: sobre la longitud de la subcua, amb llindar baix —deu missatges— i avís a l'equip de guàrdia, perquè 12.000 missatges volen dir que ningú no ho mirava.
Solució 3: El bloqueig caduca als 5 minuts mentre el consumidor continua treballant; Service Bus dona el missatge per no processat i el lliura a un altre consumidor. Quan el primer acaba i crida CompleteMessageAsync, falla amb un error de bloqueig perdut. En producció es veu com a missatges processats dues i tres vegades, un comptador de lliuraments que creix fins a esgotar-se i missatges que acaben a la subcua tot i haver-se processat correctament. Solució (a), tàctica: renovar el bloqueig automàticament mentre es treballa (MaxAutoLockRenewalDuration) i ampliar la durada del bloqueig de la subscripció. Solució (b), de disseny i millor: treure la crida lenta del consumidor; completar el missatge de seguida i delegar la part lenta en un flux a part —una orquestració de Durable Functions o una segona cua—, perquè tenir un missatge bloquejat vuit minuts limita el rendiment del sistema sencer.
Conclusió
Has resolt el problema amb què començava la lliçó. Saps per què desacoblar: la disponibilitat es multiplica a la baixa, la latència se suma i l'acoblament congela l'evolució; amb un intermediari, la compra fa l'imprescindible i publica, i un component accessori caigut deixa de tombar l'ingrés principal. Tens clara la distinció que gairebé tothom confon: un missatge és una instrucció amb destinatari que no es pot perdre; un esdeveniment és un fet en passat que l'emissor publica sense saber qui hi reacciona. I saps que el nom ho delata.
Manegues els tres serveis amb criteri. Service Bus per a missatgeria empresarial fiable: cues davant de temes amb subscripcions i filtres SQL, sessions per ordenar, bloqueig amb ullada com a mode de recepció correcte, ajornament, cua de missatges amb problemes de lliurament —la peça que salva els equips—, transaccions, detecció de duplicats i els seus tres nivells, amb el codi d'emissió i consum de reservas-confirmadas distingint l'error permanent del transitori. Event Grid per distribuir esdeveniments discrets: temes del sistema que emeten sense configurar res —el BlobCreated de sttarjetascontosopro—, temes personalitzats, esquema CloudEvents, filtratge al servei i la destinació d'esdeveniments fallits que cal configurar o els esdeveniments es perden en silenci. I Event Hubs per a ingesta massiva: particions i ordre dins de la partició, grups de consumidors independents, retenció que permet reprocessar, captura automàtica cap a la capa bronce de stlagocontosopro i compatibilitat amb Kafka. Sense oblidar que les humils cues de Storage ja basten quan hi ha un sol consumidor i cap exigència.
Has dissenyat el flux complet de Contoso veient cada decisió, i t'endus les tres conseqüències inevitables: lliurament almenys una vegada —el lliurament exactament una vegada no existeix, el que existeix és processament idempotent—, ordenació només per sessió o per partició, i idempotència obligatòria en tot consumidor. A més del cost de cada servei i el que el dispara: el sondeig en bucle, les subscripcions sense filtrar i l'escalat automàtic que puja i no baixa.
Amb això, la plataforma de Contoso està modernitzada: contenidors, orquestració, funcions, integracions i una arquitectura d'esdeveniments que la sosté. Queda fer l'últim pas del mòdul, i és d'una altra naturalesa. Contoso té ara dades que abans no podia aprofitar —milers de reclamacions de passatgers escrites en text lliure, passaports que un agent tecleja a mà a la facturació, avisos d'embarcament que només es donen en dos idiomes, un portal que no s'entén fora d'Espanya— i per a tot això existeixen serveis llestos. La lliçó següent, Serveis d'IA d'Azure, recorre aquest catàleg, implementa els casos concrets de Contoso, explica Azure OpenAI Service i la generació augmentada per recuperació per a l'assistent d'atenció al passatger, i dedica l'espai que mereix al que no és opcional: biaixos, al·lucinacions, privacitat de les dades que s'envien al servei i la revisió prèvia pels equips legal i de compliance.
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
