Ottimizzazione dell'assieme e cache
(Sezione Tecnologia e infrastruttura)
Breve riepilogo
La velocità ICI/CD nel iGaming influisce direttamente sulla velocità di rilascio, sul costo dei minuti e sulla stabilità del p99 nei picchi di carico. Chiave: cache corretta (dipendenze, manufatti, livelli contenitori, risultati intermedi di compilazione), assemblaggio incrementale e determinabilità. L'assemblaggio «buono» viene ripetuto rapidamente quando l'immissione è invariata e la cache disabile è prevedibile e controllabile.
1) Scheda della cache e cosa stiamo memorizzando
Dipendenze: pacchetti NPM/pnpm, pip wheels/Poetry, Maven/Gradle, Go della moda, Cargo crates, NuGet.
Gli artefatti intermedi della compilazione sono: «not/.cache/pip», «not/.m2», «.gradle», «not/.cargo/registry/»,« $ GOMODCACHE »,« target/», «build/»,« node _ modules/.pnpm-store ».
Livelli contenitori: Docker layer cache (BuildKit/GHA cache), cache registry-based, multi-stage.
Utensili e SDK: toolchains/microarchi (JDK, Node, Python, Rustup targets).
Mono/polirepo meta: cache Nx/Turborepo/Bazel remote-cache per attività (lint/test/build).
Dati di prova e icsture e2e - Snepshot BD compilati dalla banda UI.
Dati ML - dataset preparati, embeddings, motori compilati (TensorRT/ONNX).
2) Principi di assemblaggio rapido e prevedibile
1. Determinabilità: fissa le versioni (lockfiles), pin immagini di base, plugin hermetic e output riproduttivo.
2. Idampotenza, lo stesso assemblaggio, gli stessi manufatti e gli stessi hash.
3. Incrementalità: ricarica solo la modifica (DAG/needs/matrix/affected).
4. Locale e calore: cache accanto ai runner/nel registro, riscaldamento prima dei picchi.
5. Disabilità esplicita: chiavi della cache per lockfile/file di configurazione e hash di contenuto.
6. Igiene: TTL/« expire _ in », pulizia automatica, controllo delle dimensioni delle cache e dei manufatti.
7. Sicurezza della catena di fornitura: cache e spazzatura per i segreti; La firma SBOM/Artefatti rimane obbligatoria.
3) Docker/OCI - Immagini veloci senza perimetri
Pattern
Multi-stage (builder → runtime).
Runtime minimo (distroless/ubi-micro, solo quelli richiesti da so/ca-certs).
Ordine dei livelli: prima cambia raramente (deps), poi il codice.
«.dockerignore»: escludi «.git», test/ficsture, cache locale.
: 'cache-from/to', una cache condivisa tra i giobbe e i rami.
Esempio Dockerfile (Node + pnpm)
dockerfile syntax=docker/dockerfile:1.7
FROM node:20-bookworm AS deps
WORKDIR /app
COPY pnpm-lock.yaml./
RUN corepack enable && pnpm fetch
FROM node:20-bookworm AS builder
WORKDIR /app
COPY --from=deps /root/.cache/pnpm /root/.cache/pnpm
COPY package.json pnpm-lock.yaml./
RUN corepack enable && pnpm install --offline
COPY..
RUN pnpm build
FROM gcr.io/distroless/nodejs20 AS runtime
WORKDIR /app
COPY --from=builder /app/dist./dist
USER 10001
CMD ["dist/server.js"]
BuildKit в CI (GitHub Actions)
yaml
- uses: docker/setup-buildx-action@v3
- uses: actions/cache@v4 with:
path: /tmp/.buildx-cache key: buildx-${{ github.ref }}-${{ github.sha }}
restore-keys: buildx-${{ github.ref }}-
- uses: docker/build-push-action@v6 with:
push: true tags: ${{ env.IMAGE }}
cache-from: type=gha cache-to: type=gha,mode=max
4) Ecosistemi linguistici: cosa memorizzare e come
Java/Kotlin (Maven/Gradle)
Remote cache Gradle, parallelismo, configurazione-su-richiesta.
Chiave cache: hash build. gradle[.kts]` + lockfiles + `gradle-wrapper. properties`.
Pubblica build cache node sullo storage degli oggetti/HTTP.
Compilazione incrementale e test split per batch.
yaml
GitLab CI cache:
key: gradle-${CI_COMMIT_REF_SLUG}
paths: [.gradle/caches,.gradle/wrapper ]
script:
-./gradlew --build-cache --parallel build
Node. js (npm/pnpm/yarn)
Cache store locale («not/.npm», «}/.cache/pnpm»), chiave lockfile.
Nx/Turborepo remote-cache (S3/Redis) per attività (lint/test/build).
«turbo run build --cache-dir = .turbo» e «affected» - Tagliamo per monorepo.
Python (pip/Poetry)
Cache wheels + virtualeng; chiave dì richiements '. lock`/`poetry. lock`.
Assemblaggio wheels in una fase separata, riutilizzo tra matrici.
Per le estensioni C, «pip wheel» + «auditwheel» nell'aspetto builder.
Go
Кэш `GOMODCACHE`, `GOCACHE`; fissa «GOTOOLCHAIN »/versioni.
Condividi i passaggi: «go med download» una copia del codice «go build».
Per i grandi monoreporter - Bazel/Bazelisk o «mage» con bilico.
Rust
`~/.cargo/registry`, `~/.cargo/git`, `target/`; sccache (remoto/locale).
Condivisione della cache tra i rami dì Cargo. lock`.
C/C++
ccache/scache + chiave per flag del compilatore e versioni SDK.
Rimuove toolchain in un aspetto di base separato.
5) Bazel/Nx/Turborepo: cache di operazioni e grafica
Bazel remote cache (HTTP/Cloud) - contenuto adatto; sigillatura rigorosa, scagnozzi di sabbia.
Nx/Turborepo è la cache delle uscite di attività e l'esecuzione in monorepo.
Invalidità: dipende dall'ingresso del passo (file/flag/variabili).
6) Strategie di disabilità della cache
Chiave = hash ingressi: lockfiles, configli compilatori, manifesti.
Disabilità morbida: «restore-keys» (GHA )/prefissi (GLCI).
Disabilità rigida: rotate namespace/chiave in caso di cambiamenti critici.
Separazione livelli: deps vs source - Cambia il codice senza toccare le dipendenze pesanti.
7) Bildi e matrici incrementali
DAG/needs: avvia i giubbotti dipendenti in parallelo, non attendere sequenze.
Paths-filter - Trigger solo per i componenti interessati.
Shard test: per directory/seed, allineare la durata.
Warm-pool runner: immagini/cache pre-riscaldate prima dei picchi (tornei/campagne).
8) Artefatti vs cache: cosa differisce
Cache: input/risultati intermedi riutilizzati, area «sporca», TTL breve/media.
Artefatti - Assemblaggi finali (immagini, binari, charts), immutabili, firmati, con SBOM.
Regole: la cache viene pulita in modo aggressivo, gli artefatti sono conservati secondo la politica di rilascio.
9) Osservazione, KPI e FinOps
Metriche (pipline/repo):- Hit-rate cache (%), Warm-start vs Cold-start time, media/media durata stadio.
- Cost per pipeline/job, dimensioni cache/artefatti, larghezza di banda (jobs/hour).
- La quota "affected-runs'nel monorepo, l'intersezione senza modifiche (waste).
- Il calo dell'hit-rate è sotto la soglia, l'aumento del tempo di «build immagine», gonfiamento di manufatti, errori SLO.
10) Protezione della cache e supply chain
Nessun segreto nella cache/manufatti; mask vars, scansioni di segreti.
Pin SHA azioni esterne/plugins, solo runners affidabili.
Firma contenitori/binari (cosign), SBOM (CycloneDX/SPDX) e verifica CD.
Isolamento: namespace separati per la cache dove/stage/prod, diritti di sola lettura per i foreign branches.
11) Modelli pratici
GitHub Action - lingua + contenitore
yaml name: ci on: [push, pull_request]
concurrency: { group: ${{ github.ref }}, cancel-in-progress: true }
jobs:
build:
runs-on: ubuntu-latest steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4 with: { node-version: '20' }
- uses: actions/cache@v4 with:
path: ~/.cache/pnpm key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
- run: corepack enable && pnpm i --frozen-lockfile
- run: pnpm build
- uses: docker/build-push-action@v6 with:
tags: ${{ env.IMAGE }}
cache-from: type=gha cache-to: type=gha,mode=max
GitLab CI — Gradle remote cache
yaml variables:
GRADLE_USER_HOME: ".gradle"
cache:
key: gradle-${CI_COMMIT_REF_SLUG}
paths: [.gradle/wrapper,.gradle/caches ]
build:
stage: build script:
-./gradlew --build-cache --no-daemon build artifacts:
paths: [ "build/libs/.jar" ]
expire_in: 3 days
Jenkins — ccache/sccache
groovy pipeline {
agent { label 'cpp' }
environment { CCACHE_DIR = '/cache/ccache' }
stages {
stage('Build') {
steps {
sh 'ccache -M 10G'
sh 'cmake -B build -S. && cmake --build build -j$(nproc)'
}
}
}
post { always { sh 'ccache -s' } }
}
12) ML/dati - Accelerare gli assiemi pesanti
Cache di modelli/embedding/dataset su runner NVMe locali; versioning per hash.
Il retro dei motori come manufatti di rilascio; riutilizzo nell'inferance.
Manufatti Chunked (splits) per modelli di grandi dimensioni TTL e pulizia ritardata.
13) Assegno-foglio di implementazione
1. Fissare lockfiles e immagini di base Accendete il BuildKit.
2. Separare i livelli Docker, il codice deps; aggiungete «.dockerignore».
3. Sollevare rimote cache (Gradle/Bazel/Nx/Turbo); Creare una dipendency proxy.
4. Configurare la cache delle dipendenze in CI per lockfile; attivare le matrici e «paths-filter».
5. Immettere i biliardi incrementali e «affected only» nel monorepo.
6. Misurare hit-rate, warm/cold time, costo; Mettete fuori gli alert.
7. Attivare la firma SBOM e disabilitare i segreti nella cache.
8. Riscaldare la cache prima dei picchi; regolamentare TTL/retention.
9. Documentare la disabilità della cache e del runbooks sulla cache rotta.
10. Pulire regolarmente la cache eterna e archiviare i manufatti pesanti.
14) Antipattern
Enorme Dockerfile con passaggi spesso mutevoli prima dell'installazione dei deps.
Cache «eterna» condivisa senza chiavi/TTL, flaconcini e spazzatura.
Miscelare gli artefatti e la cache nessuna firma/SBOM.
Le versioni non ridotte degli strumenti → «cache è ma non si ripete».
Matrici per tutto a ogni PR; L'assenza di «concorrency». cancel`.
Un'unica runner senza cache calda e senza dipendency proxy.
Riepilogo
L'ottimizzazione dell'assieme è un'operazione di sistema con cache, incrementalità e determinazione. La corretta struttura di Dockerfile, remote-cache per i biliardi, dipendency proxy e disciplina di invalidità fornisce catene di montaggio veloci, a basso costo e riproducibili. Aggiungi l'osservabilità e le regole di sicurezza - e le release saranno frequenti, stabili e convenienti.