Kodeloka
  1. Kodeloka
  2. Kelas Nginx
  3. Materi

4 · Kinerja · Modul 7 dari 8

Caching & Penyajian Statis

Menyimpan balasan hulu, menyajikan berkas statis secara efisien, dan tetap melayani saat hulu tumbang.

Cache Proxy

http {
    proxy_cache_path /var/cache/nginx
                     levels=1:2
                     keys_zone=zonaku:10m
                     max_size=10g
                     inactive=60m
                     use_temp_path=off;

    server {
        location /api/ {
            proxy_cache zonaku;
            proxy_cache_key "$scheme$request_method$host$request_uri";
            proxy_cache_valid 200 301 302  10m;
            proxy_cache_valid 404          1m;

            add_header X-Cache-Status $upstream_cache_status;
        }
    }
}

Header X-Cache-Status sangat membantu saat menyetel: nilainya HIT, MISS, BYPASS, EXPIRED, STALE, atau UPDATING. Tanpa itu, menebak apakah cache benar-benar bekerja hampir mustahil.

🚫 Cache tanpa memperhatikan sesi membocorkan data antar pengguna

Bila kunci cache tidak menyertakan identitas dan balasan bersifat personal, halaman milik pengguna A akan disajikan kepada pengguna B. Ini kebocoran data yang nyata dan pernah terjadi pada banyak situs besar. Lewati cache untuk permintaan yang membawa sesi:

proxy_cache_bypass $http_authorization $cookie_sesi;
proxy_no_cache     $http_authorization $cookie_sesi;

proxy_cache_bypass membuat Nginx tidak membaca dari cache; proxy_no_cache membuatnya tidak menulis ke cache. Keduanya diperlukan.

Melayani Saat Hulu Mati

proxy_cache_use_stale error timeout updating
                       http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;

Ini salah satu konfigurasi paling berharga di Nginx. Ketika hulu tumbang, pengunjung tetap menerima versi lama alih-alih halaman galat. Dengan background_update, isi kedaluwarsa disajikan seketika sementara pembaruan berjalan di belakang layar.

💡 proxy_cache_lock mencegah serbuan ke hulu

Ketika satu entri populer kedaluwarsa, semua permintaan yang datang bersamaan dapat menembus ke hulu sekaligus — dikenal sebagai cache stampede. Direktif proxy_cache_lock mengizinkan hanya satu permintaan yang lewat, sementara sisanya menunggu hasilnya.

Berkas Statis

location /statis/ {
    root /var/www;

    sendfile       on;      # salin berkas di kernel, tanpa melewati userspace
    tcp_nopush     on;      # kirim header bersama awal berkas dalam satu paket
    tcp_nodelay    on;
    open_file_cache max=10000 inactive=30s;
    open_file_cache_valid   60s;
    open_file_cache_errors  on;

    expires 1y;
    add_header Cache-Control "public, immutable";
}
⚠️ expires 1y hanya aman untuk berkas ber-hash

Menyetel setahun pada app.js berarti pengunjung lama tidak akan pernah menerima versi baru sampai cache peramban mereka dibersihkan. Ini aman hanya bila nama berkas mengandung hash isi — app.a3f9c1.js — sehingga perubahan menghasilkan nama baru. Untuk index.html gunakan no-cache agar penunjuk ke berkas ber-hash selalu segar.

Kompresi

gzip              on;
gzip_vary         on;
gzip_min_length   1024;
gzip_comp_level   5;
gzip_proxied      any;
gzip_types        text/plain text/css application/json
                  application/javascript text/xml application/xml
                  image/svg+xml;
⚠️ Tingkat kompresi tinggi sering merugikan

gzip_comp_level 9 memakai jauh lebih banyak CPU tetapi hanya menghemat beberapa persen ukuran dibanding level 5. Pada lalu lintas tinggi, CPU itu lebih berharga daripada selisih kecil tersebut. Level 4–6 adalah titik seimbang yang lazim.

Jangan mengompresi berkas yang sudah terkompresi — JPEG, PNG, MP4, ZIP. Hasilnya justru sedikit lebih besar sekaligus membakar CPU.

Menyajikan Berkas Terkompresi Lebih Dulu

gzip_static on;      # sajikan app.js.gz bila ada, tanpa kompresi saat permintaan
brotli_static on;    # butuh modul brotli

Berkas dikompresi sekali saat proses build, lalu Nginx menyajikannya langsung. Kompresi tingkat maksimum menjadi masuk akal di sini karena hanya dilakukan sekali, bukan pada setiap permintaan.