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

  1. Per què desacoblar
  2. Missatge davant d'esdeveniment
  3. Els tres serveis comparats
  4. Azure Service Bus
  5. Azure Event Grid
  6. Azure Event Hubs
  7. El flux complet de Contoso
  8. Lliurament almenys una vegada, ordenació i idempotència
  9. Cost de cada servei
  10. Errors Comuns i Consells
  11. Exercicis
  12. Conclusió

  1. 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.

  1. 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.

  1. 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.

  1. 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, facturacion i fidelizacion, de manera que afegir un quart interessat no toca l'emissor.
  • Filtres de subscripció. Regles SQL sobre les propietats del missatge. fidelizacion nomé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-count intents 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.

  1. 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 sttarjetascontosopro emet Microsoft.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.

  1. 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 capa bronce del 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—.

  1. 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.

  1. 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.

  1. 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 sttarjetascontosopro i 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.

  1. Assigna cada necessitat a un servei i justifica l'elecció amb la distinció missatge/esdeveniment.
  2. Dissenya el tema, les subscripcions i els seus filtres per a la part de Service Bus.
  3. 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.

  1. Què va passar i per què la cua principal va continuar funcionant?
  2. Descriu el procediment per recuperar-los, indicant què cal verificar abans de reenviar.
  3. 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:

  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.
  2. Tema vuelos-completados a sb-contoso-pro, amb la subscripció millas sense filtre i la subscripció nivel-fidelidad amb el filtre esSocio = true AND millasAcreditadas > 0. Totes dues amb max-delivery-count 5 i 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ó.
  3. entorno, proyecto=contoso-millas, centro-coste=CC-2077 i propietario. 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:

  1. 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.
  2. 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 DeadLetterReason i DeadLetterErrorDescription d'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.
  3. 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

Mòdul 2: Serveis principals d'Azure

Mòdul 3: Bases de dades d'Azure

Mòdul 4: Seguretat a Azure

Mòdul 5: Azure DevOps

Mòdul 6: Serveis avançats d'Azure

Mòdul 7: Monitoratge i gestió

Mòdul 8: Gestió i optimització de costos

Mòdul 9: Estudis de cas i millors pràctiques

© Copyright 2026. Tots els drets reservats