Un sistema pot funcionar perfectament al teu portàtil amb un únic usuari i, tanmateix, ensorrar-se el dia del llançament quan arriben milers de persones alhora. El rendiment no s'endevina: es mesura. I l'única manera de saber com es comportarà un sistema sota càrrega real abans que passi és sotmetre'l a proves de càrrega controlades. En aquesta lliçó aprendràs a distingir i mesurar correctament les dues magnituds fonamentals del rendiment (latència i throughput), per què les mitjanes menteixen i has de fer servir percentils (p95, p99), els diferents tipus de prova segons el que vulguis descobrir (càrrega, estrès, soak, spike), com escriure una prova real amb k6 i JMeter, i com localitzar els colls d'ampolla que limiten el teu sistema.
Contingut
- Latència vs Throughput
- Per què les mitjanes menteixen: percentils p95/p99
- Tipus de prova de rendiment
- Exemple pràctic amb k6 i JMeter
- Identificació de colls d'ampolla
- Errors habituals i consells
- Exercicis
- Latència vs Throughput
Són les dues mètriques bàsiques del rendiment i convé no confondre-les:
- Latència: el temps que triga una petició a completar-se. Es mesura en mil·lisegons. Respon a "com de ràpid?".
- Throughput (rendiment/cabal): el nombre de peticions que el sistema processa per unitat de temps. Es mesura en peticions per segon (req/s). Respon a "quantes alhora?".
| Latència | Throughput | |
|---|---|---|
| Mesura | Temps d'una petició | Peticions per segon |
| Unitat | ms (mil·lisegons) | req/s (peticions/seg) |
| Pregunta | Com de ràpid respon? | Quant volum aguanta? |
| Ho nota | L'usuari individual | El sistema en conjunt |
L'analogia de l'autopista ho aclareix: la latència és el que triga un cotxe a recórrer-la; el throughput és quants cotxes hi passen per minut. I són independents: una autopista pot tenir molt throughput (molts carrils) però alta latència (és molt llarga). De fet, quan un sistema se satura, el throughput s'estanca mentre la latència es dispara, perquè les peticions comencen a fer cua.
- Per què les mitjanes menteixen: percentils p95/p99
Imagina que mesures la latència i obtens una mitjana de 100 ms. Sona bé... però la mitjana amaga els casos dolents. Si de cada 100 peticions, 95 triguen 50 ms i 5 triguen 1.500 ms, la mitjana continua sent baixa, però 1 de cada 20 usuaris pateix una experiència pèssima.
La solució són els percentils:
| Percentil | Significat |
|---|---|
| p50 (mediana) | La meitat de les peticions triguen menys que això |
| p95 | El 95% triga menys; el 5% pitjor queda fora |
| p99 | El 99% triga menys; reflecteix l'1% pitjor |
| p99,9 | Per a serveis molt exigents; la "cua llarga" |
Latències de 20 peticions (ms), ordenades: 40 42 45 48 50 50 52 55 58 60 62 65 70 75 80 90 110 250 800 1500 Mitjana (promig): ~135 ms <- enganyosa, la "infla" un únic valor de 1500 p50 (mediana): ~61 ms <- l'experiència típica p95: ~800 ms <- 1 de cada 20 pateix això p99: ~1500 ms <- el pitjor cas real
La regla professional: defineix els teus objectius (SLO) en percentils, no en mitjanes. Un bon objectiu és del tipus "el p95 ha d'estar per sota de 300 ms". Els percentils alts (p99, p99,9) importen especialment perquè en sistemes amb moltes dependències, una petició d'usuari activa moltes internes, i n'hi ha prou que una caigui a la cua lenta per arruïnar l'experiència.
- Tipus de prova de rendiment
No totes les proves busquen el mateix. Segons la manera d'aplicar la càrrega, distingim:
| Tipus | Què fa | Què descobreix |
|---|---|---|
| Càrrega (load) | Càrrega esperada sostinguda | Compleixo els meus SLO en condicions normals? |
| Estrès (stress) | Pujar la càrrega fins a trencar | Quin és el meu límit? Com falla? |
| Soak (resistència) | Càrrega moderada durant hores/dies | Hi ha fuites de memòria o degradació lenta? |
| Spike (pic) | Pujada brusca i sobtada | Aguanta un pic sobtat (oferta flaix, viral)? |
graph LR
L["Load: càrrega estable"]
S["Stress: puja fins a trencar"]
K["Soak: estable, moltes hores"]
P["Spike: pic sobtat"]Cada tipus respon a un risc diferent del negoci:
- La prova de càrrega valida que el sistema compleix els SLO amb el trànsit previst.
- La d'estrès revela el punt de ruptura i, crucialment, com es trenca (degrada amb elegància o col·lapsa?).
- La de soak detecta problemes que només apareixen amb el temps: fuites de memòria, connexions que no es tanquen, discos que s'omplen de logs.
- La de spike simula esdeveniments com una campanya viral o una venda flaix, comprovant si l'autoescalat reacciona a temps.
- Exemple pràctic amb k6 i JMeter
k6 és una eina moderna de proves de càrrega en què els escenaris s'escriuen com a codi JavaScript, ideal per integrar-la en CI/CD.
import http from 'k6/http';
import { check, sleep } from 'k6';
// Definim el perfil de càrrega: pugem, mantenim i baixem usuaris virtuals
export const options = {
stages: [
{ duration: '30s', target: 50 }, // Puja de 0 a 50 usuaris en 30s
{ duration: '1m', target: 50 }, // Manté 50 usuaris durant 1 minut
{ duration: '20s', target: 0 }, // Baixa a 0 (rampa de baixada)
],
thresholds: {
http_req_duration: ['p(95)<300'], // CRITERI: el p95 ha de ser < 300 ms
http_req_failed: ['rate<0.01'], // i menys de l'1% d'errors
},
};
export default function () {
const res = http.get('https://api.miempresa.com/productos');
check(res, { 'status 200': (r) => r.status === 200 }); // Verifica resposta OK
sleep(1); // Pausa d'1s simulant el "temps de lectura" de l'usuari
}Explicació detallada: el bloc stages defineix un perfil de càrrega en tres fases (rampa de pujada, planell i baixada), on target són els usuaris virtuals (VU) simultanis. Els thresholds són el cor de la prova: són els criteris d'aprovat/suspès; si el p95 supera 300 ms o els errors passen de l'1%, k6 marca la prova com a fallida (molt útil perquè un pipeline de CI/CD bloquegi un desplegament lent). La funció default és el que executa cada usuari virtual en bucle: demana la llista de productes, verifica amb check que retorna 200, i fa una pausa d'1 segon simulant comportament humà.
JMeter, d'Apache, és l'eina clàssica, basada en interfície gràfica i plans de prova en XML. És molt potent i madura, amb suport per a molts protocols. Comparativa ràpida:
| k6 | JMeter | |
|---|---|---|
| Definició de la prova | Codi (JavaScript) | GUI / XML |
| Corba d'aprenentatge | Suau per a desenvolupadors | Més pronunciada |
| Integració CI/CD | Excel·lent (nativa) | Possible, més laboriosa |
| Consum de recursos | Baix i eficient | Més gran (basat en JVM/fils) |
| Protocols | Sobretot HTTP/web | Molts (JDBC, FTP, JMS...) |
L'elecció depèn del context: k6 brilla en equips de desenvolupament i automatització; JMeter en escenaris complexos i multiprotocol o quan es prefereix una eina visual.
- Identificació de colls d'ampolla
Un coll d'ampolla (bottleneck) és el recurs que limita el rendiment de tot el sistema: per molt que milloris la resta, el sistema no anirà més ràpid que el seu component més lent. La metodologia consisteix a aplicar càrrega i observar quin recurs se satura primer.
Sospitosos habituals, per ordre de freqüència:
| Coll d'ampolla | Símptoma típic | Possible solució |
|---|---|---|
| Base de dades | CPU de la BD al 100%, consultes lentes | Índexs, memòria cau, rèpliques de lectura |
| Pool de connexions | Peticions esperant connexió lliure | Augmentar el pool, alliberar connexions abans |
| CPU de l'aplicació | CPU al 100% amb poc trànsit | Optimitzar codi, escalar horitzontalment |
| Memòria | Garbage collection freqüent, swapping | Més RAM, corregir fuites de memòria |
| Xarxa / E/S | Latència alta sense saturar la CPU | Comprimir, reduir crides, CDN |
| Bloquejos / contenció | El throughput no puja en afegir usuaris | Reduir seccions crítiques (recorda la USL) |
El procés correcte és iteratiu: trobes el coll d'ampolla, el resols, tornes a mesurar... i apareix un altre coll d'ampolla diferent (perquè ara el límit és en una altra banda). Optimitzar és anar destapant límits successius. I un advertiment essencial: no optimitzis sense mesurar abans. La intuïció sobre on és el problema sol equivocar-se; les dades d'una prova de càrrega, no.
Errors habituals i consells
- Fixar-se només en la mitjana. Amaga els casos dolents. Mesura sempre p95 i p99.
- Confondre latència amb throughput. Són coses diferents; un sistema ràpid per unitat pot tenir poc cabal i viceversa.
- Provar contra un entorn diferent del de producció. Si l'entorn de proves té la meitat de recursos o dades de joguina, els resultats no són extrapolables. Fes servir un entorn realista.
- No incloure temps d'espera realistes. Usuaris que masseguen sense pausa (
sleep) generen una càrrega irreal. Modela el comportament humà. - Optimitzar a cegues. Endevinar el coll d'ampolla malbarata esforç. Mesura, identifica i només llavors actua.
- Oblidar les proves soak. Moltes fallades (fuites de memòria) només apareixen després d'hores. No n'hi ha prou amb proves curtes.
- Consell: integra una prova de càrrega al teu CI/CD amb thresholds en percentils, perquè el rendiment sigui un criteri de qualitat automàtic i no una sorpresa en producció.
Exercicis
-
Interpretar percentils. Un servei té una latència mitjana de 80 ms, p50 de 70 ms, p95 de 600 ms i p99 de 2.000 ms. Està sa? Què et preocupa i què investigaries?
-
Triar el tipus de prova. Per a cada objectiu, indica el tipus de prova: (a) saber a partir de quants usuaris el sistema deixa de complir l'SLO; (b) comprovar si hi ha una fuita de memòria que tomba el servei després de 12 hores; (c) validar que el sistema sobreviu al pic de trànsit del llançament d'un producte.
-
Definir thresholds. El negoci exigeix que "el 99% de les peticions responguin en menys de mig segon i que fallin menys del 0,5%". Escriu el bloc
thresholdsde k6 corresponent.
Solucions
-
No està sa, malgrat la bona mitjana i mediana. El p50 de 70 ms indica que l'experiència típica és bona, però el p95 de 600 ms i, sobretot, el p99 de 2.000 ms revelen una "cua llarga": el 5% dels usuaris pateix lentitud i l'1% espera 2 segons. Investigaria què tenen en comú aquestes peticions lentes: consultes a la base de dades sense índex?, pauses de garbage collection?, crides a un servei extern lent? Les traces distribuïdes (lliçó anterior) són l'eina ideal per localitzar-ho.
-
(a) Prova d'estrès (pujar la càrrega fins a trobar el punt on s'incompleix l'SLO/es trenca). (b) Prova de soak/resistència (càrrega sostinguda durant moltes hores per detectar degradació lenta). (c) Prova de spike/pic (pujada brusca i sobtada de trànsit).
-
Bloc de thresholds:
thresholds: { http_req_duration: ['p(99)<500'], // p99 per sota de 500 ms http_req_failed: ['rate<0.005'], // menys del 0,5% d'errors }
Conclusió
Has après que el rendiment es mesura, no se suposa: que la latència (temps per petició) i el throughput (volum per segon) són magnituds diferents, que els percentils p95/p99 expliquen la veritat que la mitjana amaga, que cada tipus de prova (càrrega, estrès, soak, spike) respon a un risc diferent, com escriure proves reals amb k6 i JMeter, i com localitzar colls d'ampolla de manera iterativa i basada en dades. Validar el rendiment abans de producció és la diferència entre un llançament reeixit i un col·lapse públic.
Amb aquesta lliçó tanques el Mòdul 9, Qualitat, Seguretat i Observabilitat. Has recorregut l'escalabilitat, l'alta disponibilitat, la seguretat per disseny, l'observabilitat i el rendiment: els cinc atributs que separen una aplicació que "funciona a la meva màquina" d'un sistema robust, segur i preparat per al món real. Aquests conceptes no són fases finals, sinó criteris que han de guiar cada decisió d'arquitectura des del primer dia.
Curs d'Arquitectura d'Aplicacions
Mòdul 1: Fonaments de l'Arquitectura d'Aplicacions
- Què és l'Arquitectura d'Aplicacions?
- El Rol de l'Arquitecte de Programari
- Atributs de Qualitat i Requisits No Funcionals
- Decisions Arquitectòniques i Compromisos (Trade-offs)
- Documentació d'Arquitectura: Vistes i el Model C4
Mòdul 2: Principis i Tàctiques de Disseny
- Acoblament, Cohesió i Separació de Responsabilitats
- Principis SOLID Aplicats a l'Arquitectura
- DRY, KISS, YAGNI i Altres Principis de Disseny
- Tàctiques Arquitectòniques per als Atributs de Qualitat
- Gestió del Deute Tècnic
Mòdul 3: Estils i Patrons Arquitectònics
- Arquitectura Monolítica
- Arquitectura en Capes (N-Tier)
- Arquitectura Client-Servidor
- Arquitectura Hexagonal (Ports i Adaptadors)
- Arquitectura Neta i Ceba (Clean & Onion)
Mòdul 4: Arquitectures Distribuïdes i Microserveis
- Introducció als Sistemes Distribuïts
- Arquitectura de Microserveis
- Descomposició de Serveis i Bounded Contexts
- API Gateway, Service Discovery i Comunicació entre Serveis
- Patrons de Resiliència: Circuit Breaker, Retry i Bulkhead
- El Teorema CAP i la Consistència de Dades
Mòdul 5: Arquitectures Dirigides per Esdeveniments i Missatgeria
- Fonaments de l'Arquitectura Orientada a Esdeveniments
- Missatgeria Asíncrona: Cues i Brokers
- Patrons d'Esdeveniments: Event Sourcing i CQRS
- Gestió de Transaccions Distribuïdes: Patró Saga
- Streaming de Dades en Temps Real
Mòdul 6: Disseny Dirigit pel Domini (DDD)
- Conceptes Fonamentals del DDD
- Disseny Estratègic: Bounded Contexts i Llenguatge Ubic
- Disseny Tàctic: Entitats, Agregats i Repositoris
- Mapatge de Contextos (Context Mapping)
Mòdul 7: Dades i Persistència
- Estratègies de Persistència: SQL vs NoSQL
- Patrons d'Accés a Dades: Repository, Unit of Work i DAO
- Base de Dades per Servei i Gestió de Dades Distribuïdes
- Cau i Estratègies d'Invalidació
Mòdul 8: Arquitectura al Núvol i Desplegament
- Fonaments del Cloud Computing (IaaS, PaaS, SaaS)
- Contenidors i Orquestració amb Docker i Kubernetes
- Arquitectura Serverless
- Patrons de Disseny Cloud-Native
- Infraestructura com a Codi (IaC)
Mòdul 9: Qualitat, Seguretat i Observabilitat
- Escalabilitat: Horitzontal vs Vertical i Balanceig de Càrrega
- Alta Disponibilitat i Tolerància a Fallades
- Seguretat per Disseny i Autenticació/Autorització
- Observabilitat: Logging, Mètriques i Traçabilitat
- Rendiment i Proves de Càrrega
