Tot el que hem vist fins ara ha estat conceptual: què és un microservei, què es guanya i què es paga, com es compara amb el monòlit i quan convé fer el pas. A partir d'aquí, el curs es torna pràctic, i perquè el que és pràctic tingui sentit necessitem un cas realista que ens acompanyi de cap a cap. Aquest cas és TechCorp i la seva botiga online, techcorp-shop.

En aquesta lliçó presentem el fil conductor amb tot detall: qui és TechCorp i qui són les persones que prendran les decisions, com és el seu monòlit actual, quins problemes concrets pateix, quin és el flux de negoci central que farem servir una vegada i una altra ("un client fa una comanda"), un fragment real del codi actual que servirà de punt de partida, el mapa de serveis que construirem, l'stack tecnològic triat i un full de ruta que explica què avançarà cada mòdul sobre aquest cas. Encara no dissenyarem els límits dels serveis (això és feina del mòdul 2) ni implementarem res (mòdul 4): aquí només fixem l'escenari i les regles del joc.

Contingut

  1. Qui és TechCorp
  2. La botiga avui: un monòlit Node.js/Express amb una única PostgreSQL
  3. Les sis àrees funcionals
  4. Els problemes concrets que pateix TechCorp
  5. El flux central: "un client fa una comanda"
  6. Un fragment del monòlit actual: crearComanda
  7. El mapa objectiu de serveis
  8. L'stack tecnològic triat i per què
  9. Full de ruta del cas al llarg del curs
  10. Errors comuns i consells
  11. Exercicis
  12. Conclusió

  1. Qui és TechCorp

TechCorp és una empresa fictícia de comerç electrònic que ven productes d'electrònica de consum (auriculars, altaveus, accessoris, petits dispositius) a través de la seva botiga online techcorp-shop. Totes les dades que apareixeran al curs (clients, productes, imports, comandes) són inventades.

Dades de context que anirem fent servir:

Aspecte Situació
Antiguitat de la botiga Uns set anys en producció
Volum habitual De l'ordre de 3.000 comandes diàries en un dia normal
Pics Black Friday i rebaixes de gener: navegació pel catàleg multiplicada per 20, comandes per 3-4
Equip tècnic Unes 25 persones: desenvolupament, QA i sistemes
Organització actual Un "equip de back-end", un "equip de front-end" i un "equip de sistemes"; el back-end comença a organitzar-se informalment per àrees

Dues persones apareixeran constantment:

  • La Marta, CTO de TechCorp. És qui decideix l'estratègia tècnica, qui defensa (o no) les inversions davant la direcció i qui ha arribat a la conclusió, després d'aplicar els criteris de la lliçó anterior, que la botiga necessita evolucionar cap a microserveis de manera incremental. La Marta posarà les restriccions de negoci: no es pot aturar la botiga, no hi ha pressupost il·limitat, cada pas ha d'aportar valor.
  • El Luis, líder de l'equip de Comandes. És el responsable de l'àrea més delicada de la botiga (on es creuen clients, catàleg, estoc, pagaments i notificacions) i serà el nostre protagonista tècnic: la major part del codi que escriurem al curs serà el de servei-comandes, i moltes decisions les veurem des del seu punt de vista.

  1. La botiga avui: un monòlit Node.js/Express amb una única PostgreSQL

techcorp-shop és un únic projecte Node.js 20 amb Express, escrit en JavaScript, que s'executa com un sol procés (replicat en tres servidors idèntics darrere d'un balancejador) i que utilitza una única base de dades PostgreSQL amb totes les taules de totes les àrees.

Estructura simplificada del repositori actual:

techcorp-shop/
├── servidor.js               # arrenca Express i registra totes les rutes
├── rutes/
│   ├── clients.js
│   ├── cataleg.js
│   ├── inventari.js
│   ├── comandes.js
│   ├── pagaments.js
│   └── notificacions.js
├── controladors/
│   ├── clientsControlador.js
│   ├── catalegControlador.js
│   ├── comandesControlador.js    # aquí viu crearComanda
│   └── ...
├── bd/
│   ├── connexio.js               # un únic pool de PostgreSQL
│   └── migracions/               # totes les taules juntes
├── serveis/
│   ├── correu.js                 # enviament d'emails
│   └── passarellaPagament.js     # crida al proveïdor de pagaments
└── package.json

I l'esquema de la base de dades, molt resumit:

-- Totes a la mateixa base de dades "techcorp"
CREATE TABLE clients         (id SERIAL PRIMARY KEY, email TEXT, nom TEXT, adreca TEXT);
CREATE TABLE productes       (id SERIAL PRIMARY KEY, nom TEXT, preu NUMERIC(10,2), categoria TEXT, actiu BOOLEAN);
CREATE TABLE estoc           (producte_id INT REFERENCES productes(id), quantitat INT, reservat INT);
CREATE TABLE comandes        (id SERIAL PRIMARY KEY, client_id INT REFERENCES clients(id), estat TEXT, total NUMERIC(10,2), creat_en TIMESTAMP);
CREATE TABLE linies_comanda  (comanda_id INT REFERENCES comandes(id), producte_id INT REFERENCES productes(id), quantitat INT, preu_unitari NUMERIC(10,2));
CREATE TABLE pagaments       (id SERIAL PRIMARY KEY, comanda_id INT REFERENCES comandes(id), import NUMERIC(10,2), estat TEXT, referencia_passarella TEXT);
CREATE TABLE notificacions   (id SERIAL PRIMARY KEY, client_id INT, tipus TEXT, enviada_en TIMESTAMP);

Fixa't en les claus foranes creuades entre àrees (comandes.client_id → clients, linies_comanda.producte_id → productes, pagaments.comanda_id → comandes). Avui són una comoditat enorme; al mòdul 2 veurem que són també el principal obstacle per separar les dades.

  1. Les sis àrees funcionals

El monòlit agrupa sis àrees de negoci, que avui són carpetes i taules dins del mateix projecte i que demà seran serveis:

Àrea Què fa avui Taules principals
Clients Registre, inici de sessió, perfil, adreces d'enviament. clients
Catàleg Fitxes de producte, categories, preus, cerca. productes
Inventari Quantitats disponibles per producte, reserves en fer comanda, entrades de magatzem. estoc
Comandes Creació i cicle de vida de la comanda (pendent, confirmada, cancel·lada, enviada). comandes, linies_comanda
Pagaments Cobrament a través de la passarel·la externa, registre de pagaments i devolucions. pagaments
Notificacions Enviament de correus i SMS al client (confirmació, enviament, incidències). notificacions

Aquestes sis àrees es correspondran, una a una, amb els sis serveis del mapa objectiu. Que la correspondència sigui tan directa és una simplificació deliberada per al curs; a la vida real, trobar els límits correctes és una feina en si mateixa, que abordarem al mòdul 2.

  1. Els problemes concrets que pateix TechCorp

La Marta no vol microserveis per moda. Els vol perquè la botiga té problemes mesurables que encaixen amb els senyals de la lliçó 01-04:

  1. Desplegaments setmanals amb por. Tota la botiga es desplega els dijous a la nit. La suite de proves triga 40 minuts; el desplegament, amb comprovacions manuals, dues hores. L'últim trimestre, quatre de dotze desplegaments es van revertir totalment o parcialment. Qualsevol correcció urgent espera el dijous següent o requereix un desplegament d'emergència de tota l'aplicació.

  2. Caigudes en campanyes. L'últim Black Friday, el trànsit de navegació pel catàleg va saturar els tres servidors. Com que el catàleg comparteix procés i base de dades amb tota la resta, la creació de comandes i els cobraments també van caure: la botiga no va vendre durant 50 minuts el dia de més vendes de l'any. Per evitar-ho, sistemes va replicar tot el monòlit a deu servidors durant la campanya, pagant per capacitat de pagaments i clients que no calia.

  3. Un equip trepitjant-se. Els desenvolupadors de les diferents àrees treballen sobre el mateix repositori i les mateixes taules. Quan l'equip de Notificacions va canviar una consulta sobre comandes per a un correu nou, va trencar un informe de Comandes. Quan Comandes va afegir una columna a linies_comanda, la migració va fallar en producció per un bloqueig amb una consulta pesant de Catàleg. Els pull requests s'encallen per conflictes, i l'equip del Luis calcula que dedica un 20 % del temps a coordinar-se amb altres equips.

  4. Incidents que es propaguen. Un mes abans, una fallada del proveïdor de correu va fer que l'enviament d'emails comencés a acumular connexions obertes; la fuita de memòria va acabar tombant el procés sencer, cobraments inclosos.

  5. Model de dades del catàleg forçat. Els productes tenen atributs molt variables (uns tenen talla, altres voltatge, altres compatibilitat) i a PostgreSQL s'ha acabat amb una taula atributs_producte genèrica de clau-valor incòmoda de consultar i de mantenir.

Aquests cinc problemes són el "perquè" de tot el curs. Cada mòdul posterior en resoldrà algun.

  1. El flux central: "un client fa una comanda"

De tots els fluxos de la botiga, n'hi ha un que els travessa tots: un client fa una comanda. És el flux que més valor té per al negoci, el que més àrees implica i el que més problemes concentra. Per això serà l'exemple recurrent de tot el curs: el modelarem, el dividirem, l'implementarem, el desplegarem, el monitorarem i l'assegurarem.

Els passos, tal com passen avui al monòlit:

  1. El client, ja identificat, envia el seu cistell (clientId i una llista de producteId amb quantitats).
  2. Es comprova que el client existeix i se'n recupera l'adreça.
  3. Es consulten els productes per obtenir-ne el nom i el preu actual.
  4. Es comprova l'estoc de cada producte i es reserva (s'incrementa estoc.reservat).
  5. Es calcula el total i es crea la comanda en estat PENDENT amb les seves línies.
  6. Es cobra cridant la passarel·la de pagament externa i es registra el pagament.
  7. Si el cobrament va bé, la comanda passa a CONFIRMADA, l'estoc reservat es descompta definitivament i s'envia el correu de confirmació.
  8. Si el cobrament falla, s'allibera la reserva d'estoc, la comanda passa a CANCELLADA i s'envia un correu d'incidència.

Tot això passa dins d'una única petició HTTP i, gairebé tot, dins d'una única transacció de base de dades.

sequenceDiagram
    autonumber
    actor C as Client
    participant M as Monòlit techcorp-shop
    participant BD as PostgreSQL (única)
    participant PP as Passarel·la de pagament (externa)
    participant SMTP as Servidor de correu (extern)

    C->>M: POST /comandes {clientId, linies}
    M->>BD: BEGIN
    M->>BD: SELECT client
    M->>BD: SELECT productes (preu)
    M->>BD: UPDATE estoc SET reservat = reservat + quantitat
    M->>BD: INSERT comanda (PENDENT) + linies
    M->>PP: cobrar(total)
    alt cobrament correcte
        PP-->>M: OK, referència
        M->>BD: INSERT pagament; UPDATE comanda = CONFIRMADA; UPDATE estoc (descomptar)
        M->>BD: COMMIT
        M->>SMTP: enviar correu de confirmació
        M-->>C: 201 Created {comandaId, estat: CONFIRMADA}
    else cobrament rebutjat
        PP-->>M: rebutjat
        M->>BD: ROLLBACK (desfà reserva i comanda)
        M->>SMTP: enviar correu d'incidència
        M-->>C: 402 Payment Required
    end

Quan la botiga estigui dividida en serveis, aquest mateix flux es convertirà en una coreografia d'esdeveniments: servei-comandes crearà la comanda i publicarà comanda.creada; servei-inventari reservarà estoc i publicarà estoc.reservat; servei-pagaments cobrarà i publicarà pagament.confirmat; servei-comandes confirmarà la comanda i publicarà comanda.confirmada (o comanda.cancellada si alguna cosa falla); i servei-notificacions enviarà el correu. Aquesta versió la dissenyarem al mòdul 2 i la construirem al 4; de moment, queda't amb la versió monolítica i amb els noms dels esdeveniments, que reapareixeran constantment:

Esdeveniment Qui el publica Què significa
comanda.creada servei-comandes S'ha registrat una comanda en estat PENDENT.
estoc.reservat servei-inventari L'estoc de les línies de la comanda ha quedat reservat.
pagament.confirmat servei-pagaments La passarel·la ha acceptat el cobrament.
comanda.confirmada servei-comandes La comanda està completa: estoc i pagament correctes.
comanda.cancellada servei-comandes La comanda no s'ha pogut completar (sense estoc, pagament rebutjat...).

  1. Un fragment del monòlit actual: crearComanda

Aquest és, simplificat però fidel a l'esperit del codi real, el controlador Express que avui implementa el flux anterior. Llegeix-lo amb calma: és el punt de partida de tot el curs, i hi tornarem per descompondre'l (mòdul 2), extreure'n serveis (mòdul 4) i comparar-lo amb el resultat final (mòdul 8).

// controladors/comandesControlador.js  (monòlit techcorp-shop, versió actual)
const bd = require('../bd/connexio');            // únic pool de PostgreSQL
const passarellaPagament = require('../serveis/passarellaPagament');
const correu = require('../serveis/correu');

async function crearComanda(req, res) {
  const { clientId, linies } = req.body;          // linies: [{ producteId, quantitat }]
  const client = await bd.connectar();            // una connexió per a tota l'operació

  try {
    await client.query('BEGIN');

    // 1. Dades del client (taula d'UNA ALTRA àrea: clients)
    const { rows: [dadesClient] } = await client.query(
      'SELECT id, email, nom FROM clients WHERE id = $1', [clientId]);
    if (!dadesClient) throw new Error('CLIENT_NO_EXISTEIX');

    // 2. Preus actuals (taula d'UNA ALTRA àrea: catàleg)
    const ids = linies.map(l => l.producteId);
    const { rows: productes } = await client.query(
      'SELECT id, nom, preu FROM productes WHERE id = ANY($1) AND actiu = true', [ids]);
    if (productes.length !== ids.length) throw new Error('PRODUCTE_NO_DISPONIBLE');

    // 3. Comprovar i reservar estoc (taula d'UNA ALTRA àrea: inventari)
    let total = 0;
    for (const linia of linies) {
      const producte = productes.find(p => p.id === linia.producteId);
      const { rowCount } = await client.query(
        `UPDATE estoc SET reservat = reservat + $1
          WHERE producte_id = $2 AND quantitat - reservat >= $1`,
        [linia.quantitat, linia.producteId]);
      if (rowCount === 0) throw new Error('SENSE_ESTOC');
      total += producte.preu * linia.quantitat;
    }

    // 4. Crear la comanda i les seves línies (taules pròpies de l'àrea de comandes)
    const { rows: [comanda] } = await client.query(
      `INSERT INTO comandes (client_id, estat, total, creat_en)
       VALUES ($1, 'PENDENT', $2, NOW()) RETURNING id`, [clientId, total]);
    for (const linia of linies) {
      const producte = productes.find(p => p.id === linia.producteId);
      await client.query(
        `INSERT INTO linies_comanda (comanda_id, producte_id, quantitat, preu_unitari)
         VALUES ($1, $2, $3, $4)`, [comanda.id, linia.producteId, linia.quantitat, producte.preu]);
    }

    // 5. Cobrar (crida síncrona a un proveïdor extern, enmig de la transacció)
    const resultatCobrament = await passarellaPagament.cobrar({ import: total, clientId, comandaId: comanda.id });
    if (!resultatCobrament.ok) throw new Error('PAGAMENT_REBUTJAT');

    // 6. Registrar pagament i confirmar (taula d'UNA ALTRA àrea: pagaments)
    await client.query(
      `INSERT INTO pagaments (comanda_id, import, estat, referencia_passarella)
       VALUES ($1, $2, 'CONFIRMAT', $3)`, [comanda.id, total, resultatCobrament.referencia]);
    await client.query(`UPDATE comandes SET estat = 'CONFIRMADA' WHERE id = $1`, [comanda.id]);
    for (const linia of linies) {
      await client.query(
        `UPDATE estoc SET quantitat = quantitat - $1, reservat = reservat - $1 WHERE producte_id = $2`,
        [linia.quantitat, linia.producteId]);
    }

    await client.query('COMMIT');

    // 7. Enviar email (àrea de notificacions), fora de la transacció però a la mateixa petició
    await correu.enviar({
      a: dadesClient.email,
      assumpte: `Comanda ${comanda.id} confirmada`,
      cos: `Hola ${dadesClient.nom}, la teva comanda per ${total} € està confirmada.`
    });

    return res.status(201).json({ comandaId: comanda.id, estat: 'CONFIRMADA', total });

  } catch (error) {
    await client.query('ROLLBACK');
    const codis = { CLIENT_NO_EXISTEIX: 404, PRODUCTE_NO_DISPONIBLE: 400, SENSE_ESTOC: 409, PAGAMENT_REBUTJAT: 402 };
    return res.status(codis[error.message] || 500).json({ error: error.message });
  } finally {
    client.alliberar();
  }
}

module.exports = { crearComanda };

Què cal observar en aquest codi, perquè cada punt serà un tema del curs:

  • Una funció fa sis coses de cinc àrees diferents: valida client, consulta catàleg, reserva inventari, crea comanda, cobra i notifica. És fàcil de llegir, però qualsevol canvi en qualsevol àrea passa per aquí.
  • Accés directe a taules d'altres àrees (clients, productes, estoc, pagaments). És el que fa impossible que Notificacions canviï el seu esquema sense avisar Comandes, i viceversa. La lliçó 02-04 tractarà precisament de trencar això.
  • Una transacció ho protegeix tot: si el pagament falla, el ROLLBACK desfà la reserva d'estoc i la comanda. És la comoditat que perdrem en separar bases de dades i que la lliçó 02-05 substituirà amb una saga.
  • Una crida externa (la passarel·la de pagament) dins de la transacció: mentre la passarel·la respon (de vegades segons), les files d'estoc queden bloquejades per a totes les altres comandes. En campanyes, això contribueix a la saturació.
  • L'enviament de correu és síncron: si el servidor de correu triga o falla, la resposta al client triga o falla, encara que la comanda estigui perfectament cobrada. Això és el que les notificacions asíncrones per esdeveniments resoldran al mòdul 3.
  • Sense idempotència: si el client prem dues vegades "comprar", es creen dues comandes i es cobra dues vegades. Avui ho evita el front-end; en un sistema distribuït, no serà suficient.

  1. El mapa objectiu de serveis

Aquest és el sistema que anirem construint. Els noms, ports i bases de dades són fixos per a tot el curs; els reutilitzarem al codi, als fitxers de Docker Compose i als manifests de Kubernetes.

Servei Port Responsabilitat Base de dades
servei-clients 3004 Registre, autenticació de clients (delegada a Keycloak), perfil i adreces. PostgreSQL (clients)
servei-cataleg 3001 Fitxes de producte, categories, preus, cerca. Alta lectura. MongoDB (cataleg)
servei-inventari 3006 Estoc disponible, reserves i alliberaments, entrades de magatzem. PostgreSQL (inventari)
servei-comandes 3002 Creació i cicle de vida de la comanda; coordina el flux mitjançant esdeveniments. PostgreSQL (comandes)
servei-pagaments 3003 Cobraments contra la passarel·la externa, registre de pagaments i devolucions. PostgreSQL (pagaments)
servei-notificacions 3005 Enviament de correus i SMS a partir d'esdeveniments d'altres serveis. Sense base de dades pròpia rellevant (cua de RabbitMQ i registre mínim d'enviaments)
API Gateway 8080 Punt d'entrada únic: encaminament, autenticació JWT, límits d'ús.

I la infraestructura de suport que envoltarà els serveis:

Peça Paper
RabbitMQ Broker de missatges per als esdeveniments comanda.creada, estoc.reservat, pagament.confirmat, comanda.confirmada, comanda.cancellada.
Keycloak Servidor d'identitat (OAuth2 / OpenID Connect) que emet els JWT que el gateway i els serveis validen.
Prometheus, Grafana, Loki Mètriques, panells i logs centralitzats.
OpenTelemetry + Jaeger Traces distribuïdes per seguir una comanda a través de tots els serveis.
Docker / Docker Compose Empaquetat i entorn local de desenvolupament.
Kubernetes (+ Istio) Orquestració en producció i malla de serveis.
GitHub Actions Pipelines d'integració i desplegament continu.
flowchart TB
    Client[Navegador / App mòbil] --> GW[API Gateway :8080]
    KC[Keycloak] -. JWT .-> GW
    GW --> CLI[servei-clients :3004]
    GW --> CAT[servei-cataleg :3001]
    GW --> COM[servei-comandes :3002]
    CLI --> BD1[(PG clients)]
    CAT --> BD2[(MongoDB)]
    COM --> BD3[(PG comandes)]
    INV[servei-inventari :3006] --> BD4[(PG inventari)]
    PAG[servei-pagaments :3003] --> BD5[(PG pagaments)]
    NOT[servei-notificacions :3005]
    COM <-. esdeveniments .-> MQ[(RabbitMQ)]
    MQ <-. esdeveniments .-> INV
    MQ <-. esdeveniments .-> PAG
    MQ -. esdeveniments .-> NOT
    PAG --> PP[Passarel·la de pagament externa]
    NOT --> SMTP[Correu / SMS extern]

  1. L'stack tecnològic triat i per què

La Marta i els líders d'equip han fixat l'stack amb dos criteris: continuïtat amb el que l'equip ja coneix (per no aprendre un llenguatge nou alhora que una arquitectura nova) i estàndards de mercat per a la resta de peces.

Decisió Elecció Per què
Llenguatge i framework dels serveis Node.js 20 + Express (JavaScript) És el que ja fa servir el monòlit; l'equip el domina. Els microserveis permetrien altres llenguatges, però TechCorp no té avui cap raó per fer-ho. Identificadors en català (crearComanda, ComandaRepositori, clientId) per coherència amb el codi existent.
Base de dades relacional PostgreSQL (una per servei) Ja es coneix i s'opera; encaixa amb comandes, pagaments, inventari i clients, on importen les transaccions locals.
Base de dades del catàleg MongoDB Resol el problema real dels atributs variables de producte. És l'únic cas d'heterogeneïtat justificada.
Missatgeria RabbitMQ Broker madur, senzill d'operar a l'escala de TechCorp, amb suport de confirmacions i cues d'errors.
Empaquetat i entorn local Docker i Docker Compose Estàndard de facto; permet aixecar tota la botiga en un portàtil.
Orquestració Kubernetes Estàndard de facto per operar contenidors en producció; l'equip de sistemes ja l'ha provat.
CI/CD GitHub Actions El codi ja és a GitHub; s'evita una altra eina.
Observabilitat Prometheus, Grafana, Loki, OpenTelemetry, Jaeger Conjunt de codi obert àmpliament usat que cobreix mètriques, panells, logs i traces.
Seguretat JWT/OAuth2 amb Keycloak Identitat centralitzada i estàndard; els serveis només validen tokens.
Malla de serveis Istio Xifratge entre serveis, polítiques i observabilitat de xarxa sense tocar el codi dels serveis. S'introdueix al final, quan la resta ja funciona.

Una nota important per al teu aprenentatge: aquestes eleccions són raonables, no les úniques. A la lliçó 04-01 discutirem alternatives (Kafka enfront de RabbitMQ, altres llenguatges, altres orquestradors). Aquí simplement fixem el terreny perquè tots els exemples del curs siguin coherents.

  1. Full de ruta del cas al llarg del curs

Així avançarà la història de TechCorp mòdul a mòdul. Cada fila respon a la pregunta "què li passa a la botiga en aquest mòdul?".

Mòdul Què avança el cas de TechCorp Problema de TechCorp que ataca
1. Introducció (aquest) Es fixa l'escenari, el flux central i el mapa objectiu. La Marta decideix migrar de manera incremental. Entendre el perquè.
2. Disseny S'analitzen les sis àrees, se'n defineixen els límits (bounded contexts), es decideix quines dades són de qui i com se substitueix la gran transacció de crearComanda per una saga basada en esdeveniments. Equips que es trepitgen; transacció única.
3. Comunicació Es dissenyen les APIs REST de cada servei, els esdeveniments de RabbitMQ del flux de comanda, el gateway al 8080, com es troben els serveis i com es versionen els contractes. Acoblament entre àrees; correu síncron.
4. Implementació Es construeixen de debò els serveis en Node.js/Express, començant per servei-comandes amb el Luis: configuració, consum d'APIs, publicació d'esdeveniments i proves (unitàries, d'integració, de contracte). Punt de partida real del codi.
5. Desplegament S'empaqueten els serveis en Docker, s'aixeca la botiga amb Docker Compose i després a Kubernetes, es munten pipelines a GitHub Actions i es desplega servei-cataleg en canary. S'afegeix Istio. Desplegaments setmanals amb por.
6. Monitoratge S'instrumenten mètriques, logs i traces del flux de comanda; es dissenyen reintents, circuit breakers i cues d'errors; s'escala el catàleg per al Black Friday; es defineixen SLOs i alertes. Caigudes en campanyes; incidents que es propaguen.
7. Seguretat Es protegeix el gateway amb JWT de Keycloak, es xifra la comunicació entre serveis i s'endureixen contenidors i clúster. Superfície d'atac d'un sistema distribuït.
8. Casos d'estudi Es recorre la migració completa de cap a cap (patró strangler), es veu la implementació i el desplegament complets del sistema, i se n'extreuen lliçons. Consolidar-ho tot.
flowchart LR
    M1[M1<br/>Escenari] --> M2[M2<br/>Disseny de límits<br/>i dades] --> M3[M3<br/>APIs, esdeveniments<br/>i gateway] --> M4[M4<br/>Codi dels<br/>serveis]
    M4 --> M5[M5<br/>Docker, K8s,<br/>CI/CD] --> M6[M6<br/>Observabilitat<br/>i resiliència] --> M7[M7<br/>Seguretat] --> M8[M8<br/>Migració completa<br/>i lliçons]

Un detall que convé tenir present des d'ara: el curs no fa cap "big bang". TechCorp no apagarà el monòlit un divendres per engegar sis serveis el dilluns. Els serveis s'extrauran un per un, començant pel catàleg (la raó d'escalat més clara i el risc més baix), després el flux de comandes, i el monòlit s'anirà aprimant fins a desaparèixer. Aquest procés incremental es detalla a la lliçó 08-01.

Errors Comuns i Consells

  • Perdre de vista el perquè. Quan al mòdul 5 t'estiguis barallant amb un manifest de Kubernetes, recorda els cinc problemes de l'apartat 4: cada peça d'infraestructura hi és per resoldre'n un, no per si mateixa.
  • Idealitzar el punt d'arribada. El mapa de serveis de l'apartat 7 és l'objectiu, però es construirà pas a pas, i algunes decisions es revisaran pel camí (és el normal en un projecte real).
  • Menysprear el codi del monòlit. crearComanda és un codi raonable per a un monòlit; no és "dolent", és inadequat per al problema que TechCorp té ara. Entendre'l bé és la clau per descompondre'l bé.
  • Canviar els noms. Mantén els noms de serveis, ports i esdeveniments exactament com apareixen a les taules d'aquesta lliçó; la resta del curs els dona per suposats.
  • Consell: guarda una còpia mental (o real) del diagrama de seqüència de l'apartat 5. El compararàs amb la seva versió en esdeveniments al mòdul 2 i amb la traça distribuïda real al mòdul 6, i aquesta comparació és una de les millors maneres d'entendre què canvia amb els microserveis.

Exercicis

Exercici 1: Traçar el flux

Sense mirar el diagrama de seqüència, escriu en ordre els vuit passos del flux "un client fa una comanda" tal com passa avui al monòlit, i indica per a cada pas a quina àrea funcional pertany.

Exercici 2: Llegir crearComanda amb ulls d'arquitecte

Sobre el fragment de l'apartat 6, respon:

  1. Quines taules consulta o modifica que no pertanyen a l'àrea de comandes?
  2. Què passa si la passarel·la de pagament triga 15 segons a respondre? A qui afecta?
  3. Què passa si l'enviament del correu falla després del COMMIT? Què veu el client i què queda a la base de dades?

Exercici 3: Relacionar problemes i mòduls

Per a cadascun dels cinc problemes de l'apartat 4, indica quin mòdul (o mòduls) del curs l'abordaran i amb quina peça del mapa objectiu o de l'stack es relaciona.

Solucions

Exercici 1

  1. El client envia el cistell → Comandes (punt d'entrada).
  2. Comprovar client i recuperar adreça → Clients.
  3. Consultar productes i preus → Catàleg.
  4. Comprovar i reservar estoc → Inventari.
  5. Calcular total i crear comanda PENDENTComandes.
  6. Cobrar a la passarel·la i registrar el pagament → Pagaments.
  7. Confirmar comanda, descomptar estoc i enviar correu → Comandes, Inventari i Notificacions.
  8. Si el cobrament falla: alliberar reserva, cancel·lar i notificar incidència → Inventari, Comandes i Notificacions.

Exercici 2

  1. clients (àrea de clients), productes (catàleg), estoc (inventari) i pagaments (pagaments). Només comandes i linies_comanda són pròpies.
  2. La transacció continua oberta durant aquests 15 segons, amb les files d'estoc d'aquests productes bloquejades per l'UPDATE. Qualsevol altra comanda que inclogui algun d'aquests productes es queda esperant. En una campanya, moltes comandes esperant bloquejos esgoten les connexions i el sistema sencer es degrada. A més, el client veu la pàgina "carregant" durant 15 segons.
  3. La comanda està confirmada, cobrada i amb l'estoc descomptat a la base de dades (el COMMIT ja s'ha executat). Però correu.enviar llança una excepció, el catch executa un ROLLBACK (que ja no desfà res, perquè la transacció ha acabat) i respon al client amb un 500. El client creu que la seva compra ha fallat, tot i que se li ha cobrat; probablement ho tornarà a intentar i se li cobrarà dues vegades. És un exemple perfecte de per què les notificacions han de ser asíncrones i desacoblades.

Exercici 3

Problema Mòduls Peces relacionades
Desplegaments setmanals amb por 5 (Docker, Kubernetes, CI/CD, estratègies de desplegament) i 4 (proves per servei) GitHub Actions, contenidors, desplegament canary
Caigudes en campanyes 6 (escalabilitat, resiliència) i 2/3 (catàleg com a servei a part) servei-cataleg escalat independentment, Prometheus/Grafana
Un equip trepitjant-se 2 (límits i una base de dades per servei) i 3 (contractes) Bounded contexts, APIs versionades
Incidents que es propaguen 3 (missatgeria asíncrona) i 6 (gestió d'errors, circuit breakers) RabbitMQ, servei-notificacions aïllat
Model de dades del catàleg forçat 2 (una base de dades per servei) i 4 (implementació) MongoDB a servei-cataleg

Conclusió

En aquesta lliçó hem presentat a fons el cas que vertebra el curs: TechCorp, una botiga online que avui és un monòlit Node.js/Express sobre una única PostgreSQL amb sis àrees funcionals, i que pateix problemes concrets i mesurables: desplegaments setmanals temuts, caigudes en campanyes per saturació del catàleg, equips que es trepitgen sobre el mateix codi i les mateixes taules, incidents que es propaguen d'àrees secundàries a les crítiques i un model de dades forçat al catàleg. Hem recorregut pas a pas el flux central "un client fa una comanda" i hem llegit el codi real de crearComanda, que concentra en una sola funció i una sola transacció la feina de cinc àrees: aquest fragment és el nostre punt de partida. Hem fixat el mapa objectiu (sis serveis amb els seus ports i bases de dades més un gateway), l'stack tecnològic i les seves raons, els cinc esdeveniments del flux de comanda i un full de ruta mòdul a mòdul.

Amb l'escenari definit, el mòdul 2 comença la feina de debò: dissenyar els microserveis. Partirem dels principis de disseny, aprendrem a descompondre el monòlit de TechCorp, en definirem els bounded contexts, decidirem com repartir les dades entre serveis i substituirem la gran transacció de crearComanda per una saga coordinada mitjançant esdeveniments. La Marta ha pres la decisió; a partir d'ara acompanyem el Luis i el seu equip en l'execució.

Curs de Microserveis

Mòdul 1: Introducció als Microserveis

Mòdul 2: Disseny de Microserveis

Mòdul 3: Comunicació entre Microserveis

Mòdul 4: Implementació de Microserveis

Mòdul 5: Desplegament i Orquestració

Mòdul 6: Monitoratge i Manteniment

Mòdul 7: Seguretat en Microserveis

Mòdul 8: Casos d'Estudi i Exemples Pràctics

© Copyright 2026. Tots els drets reservats