Pengembangan Web

OPcache PHP Saat Deployment - Jadikan Kode Baru Aktif dengan Sengaja, Bukan Kebetulan

OPcache PHP Saat Deployment - Jadikan Kode Baru Aktif dengan Sengaja, Bukan Kebetulan

Sebuah deployment mengganti file PHP di disk, tetapi itu saja belum menjawab instruksi hasil kompilasi mana yang akan dijalankan oleh proses PHP berumur panjang pada request berikutnya. Jika OPcache terlibat, kapan kode baru mulai aktif: seketika, setelah interval singkat, setelah invalidation eksplisit, atau hanya setelah proses yang relevan di-restart?

Jawaban yang berguna bukanlah "selalu bersihkan cache." Yang diperlukan adalah memilih kontrak freshness yang sesuai dengan metode deployment, lalu memverifikasi kontrak itu pada runtime yang sama dengan yang melayani request web. Artikel ini membahas masalah operasional yang sempit tersebut untuk aplikasi PHP kecil. Artikel ini tidak menjanjikan zero-downtime deployment, menentukan satu nama service PHP-FPM, atau memperkirakan peningkatan performa yang belum diukur.

OPcache memiliki satu tugas khusus

PHP biasanya melakukan parsing dan kompilasi sebuah script sebelum menjalankannya. Pengantar OPcache resmi menjelaskan bahwa OPcache menyimpan bytecode script yang sudah dikompilasi di shared memory sehingga proses memuat dan parsing berulang dapat dihindari pada request berikutnya. Itulah perannya yang berguna sekaligus terbatas.

OPcache bukan HTTP response cache, database cache, package cache Composer, ataupun application data cache. Melakukan purge pada CDN tidak menyegarkan bytecode PHP. Menjalankan composer install juga tidak dengan sendirinya menentukan kapan runtime PHP berumur panjang mengenali setiap script yang berubah. Menganggap semua lapisan ini sekadar "cache" membuat kegagalan deployment lebih sulit dilacak.

OPcache juga memiliki lebih dari satu mode penyimpanan. Cache in-memory yang normal dan file cache opsional bukan hal yang dapat dipertukarkan. Perbedaan ini penting nanti: fungsi opcache_reset() yang didokumentasikan mereset cache in-memory, bukan file cache.

Timestamp validation adalah kebijakan freshness

Pengaturan utamanya adalah opcache.validate_timestamps. Menurut konfigurasi runtime OPcache PHP, saat opsi ini aktif, OPcache memeriksa script yang diperbarui berdasarkan opcache.revalidate_freq. Frekuensi 0 memeriksa pembaruan pada setiap request. Nilai positif mengizinkan sebuah interval ketika bytecode yang tersimpan masih dapat digunakan sebelum timestamp diperiksa lagi.

; Illustrative policy: check script timestamps on every request.
opcache.validate_timestamps=1
opcache.revalidate_freq=0

Kebijakan ini mudah dipahami untuk situs sederhana: menerbitkan satu file baru yang lengkap memungkinkan OPcache mendeteksi perubahan timestamp-nya pada request berikutnya. "Periksa setiap request" bukan berarti "nonaktifkan OPcache"; bytecode hasil kompilasi tetap dapat digunakan kembali ketika source tidak berubah. Pemeriksaan tersebut mungkin menambah pekerjaan, tetapi biayanya bergantung pada aplikasi, filesystem, traffic, dan build PHP. Benchmark dari server lain tidak dapat menentukan apakah biaya itu berarti di sini.

Interval revalidation yang positif juga merupakan kebijakan valid selama proses release menerima freshness window-nya. Jika intervalnya dua detik, misalnya, kontraknya bukan "kode baru aktif seketika." Kontraknya adalah OPcache memeriksa secara berkala berdasarkan interval yang dikonfigurasi. Deployment dan smoke test tidak seharusnya mengklaim perilaku yang lebih kuat daripada yang diberikan konfigurasi.

Menonaktifkan validation berarti memindahkan tanggung jawab

Dengan opcache.validate_timestamps=0, manual PHP menyatakan bahwa perubahan filesystem memerlukan reset manual, targeted invalidation, atau restart web server yang relevan sebelum perubahan berlaku. Cara ini dapat menghilangkan pemeriksaan timestamp dari jalur request, tetapi tidak menghilangkan pekerjaan menjaga freshness. Tanggung jawab itu berpindah ke prosedur deployment.

; Use only when every release has a reliable refresh step.
opcache.validate_timestamps=0

Pertukaran tersebut dapat masuk akal dalam sistem release yang terkendali. Alasannya lebih lemah ketika file diedit langsung, release disalin secara manual, atau operator tidak dapat menyatakan proses mana yang memiliki cache. Dalam kondisi seperti itu, validation yang dinonaktifkan dapat mempertahankan bytecode lama tanpa batas setelah source berubah. Pengaturan yang disalin sebagai "optimasi production" diam-diam berubah menjadi dependency bagi correctness.

Konfigurasi sendiri memiliki lifecycle. Dokumentasi file konfigurasi PHP menjelaskan bahwa pemuatan konfigurasi bergantung pada Server API atau SAPI. PHP server-module membaca konfigurasinya saat startup, sedangkan CGI dan CLI membacanya pada setiap invocation; file khusus SAPI dan file INI tambahan yang dipindai juga dapat berlaku. Karena itu, mengedit file INI tidak membuktikan bahwa proses web yang sudah berjalan telah menggunakannya.

Invalidate, reset, dan restart menjawab pertanyaan berbeda

Invalidate satu script yang diketahui

opcache_invalidate() menargetkan satu script. Tanpa argumen force, fungsi tersebut hanya melakukan invalidation ketika waktu modifikasi source lebih baru daripada bytecode yang tersimpan; dengan force=true, invalidation dilakukan tanpa bergantung pada perbandingan tersebut. Jika file cache OPcache aktif, fungsi yang didokumentasikan ini juga melakukan invalidation terhadap entry file cache yang sesuai.

Cara ini presisi ketika deployment mengetahui file mana saja yang berubah. Cara tersebut menjadi rumit ketika sebuah release mengubah ratusan script, menghapus file, membuat ulang autoloader, atau mengubah hubungan antarkelas. Daftar pemanggilan per file yang berhasil tidak otomatis membuktikan bahwa release tersebut kompatibel secara internal.

Reset cache in-memory

opcache_reset() mereset seluruh opcode cache in-memory. Script dimuat dan di-parse kembali saat request berikutnya mengakses script tersebut. Fungsi ini tidak mereset file cache opsional, dan dapat mengembalikan false ketika OPcache nonaktif atau restart sedang menunggu maupun berlangsung.

Full reset lebih luas dan sederhana daripada menyebutkan semua file, tetapi juga membuang entry hasil kompilasi yang masih berguna dan membuat request berikutnya membangunnya kembali. Lebih penting lagi, fungsi reset harus berjalan dalam konteks cache yang memang relevan. Membuat endpoint web tanpa autentikasi yang menyediakan kemampuan reset bukan jalan pintas yang masuk akal; tindakan itu menambah control surface di production dan dapat mengubah request berulang menjadi gangguan.

Kelola proses yang melayani request

Operasi lifecycle proses dapat memberikan batas yang lebih jelas ketika timestamp validation dinonaktifkan atau ketika perubahan konfigurasi harus dimuat. Command yang tepat bergantung pada sistem operasi, packaging PHP, SAPI, service manager, dan kebutuhan availability. Me-restart nama service tebakan dari tutorial umum bukanlah desain deployment.

Restart dapat menginterupsi pekerjaan; graceful reload dapat membuat worker lama dan baru aktif bersamaan; dan keduanya dapat gagal. Karena itu, deployment membutuhkan definisi unit yang sebenarnya, perilakunya yang terdokumentasi, health check, log terbaru, serta jalur rollback. "Command selesai dengan exit zero" adalah bukti yang lebih sempit daripada "release yang dimaksud sekarang melayani respons yang benar."

Jangan meminta CLI berbicara atas nama PHP-FPM

Command seperti berikut berguna, tetapi menjelaskan invocation CLI:

php --ini
php --ri "Zend OPcache"

Konfigurasi runtime mendokumentasikan opcache.enable_cli secara terpisah, dan default yang didokumentasikan adalah nonaktif. Aturan file konfigurasi juga memungkinkan SAPI memuat file berbeda. Akibatnya, output CLI mungkin tidak menjelaskan worker PHP-FPM yang melayani situs. Output tersebut adalah bukti untuk satu runtime, bukan otomatis untuk semua runtime.

Untuk runtime web, kumpulkan pengaturan yang diperlukan melalui diagnostic administratif yang dilindungi, instrumentation deployment, atau configuration management. Jangan menerbitkan halaman phpinfo() lengkap. Halaman itu dapat mengungkap path, module, detail environment, serta konfigurasi yang tidak perlu menjadi informasi publik.

Jika kebijakan akses mengizinkan, opcache_get_status(false) dapat melaporkan state untuk instance cache in-memory saat ini tanpa mencantumkan setiap script yang tersimpan. Field yang didokumentasikan mencakup apakah cache aktif atau penuh, state restart, penggunaan memory, dan statistics. Fungsi ini tidak melaporkan file cache, dan opcache.restrict_api dapat mencegah akses. Batasan tersebut adalah bagian dari cara menafsirkan hasil, bukan gangguan yang harus diterobos.

Bytecode baru tidak dapat memperbaiki publikasi file yang tidak aman

opcache.file_update_protection milik OPcache mencegah caching file yang usianya lebih muda daripada jumlah detik yang dikonfigurasi. Dokumentasi PHP menyajikannya sebagai perlindungan agar file yang belum selesai diperbarui tidak masuk cache dan mencatat bahwa nilainya dapat diatur ke nol ketika semua update dilakukan secara atomic.

Pengaturan itu tidak boleh dianggap sebagai transaksi deployment yang lengkap. Jika file ditimpa satu per satu di direktori live, request yang berbeda dapat melihat campuran state beberapa release. Satu script mungkin merujuk class atau function yang belum diterima file lain. Pemeriksaan timestamp dapat mengenali perubahan; pemeriksaan itu tidak dapat membuat penyalinan banyak file menjadi atomic.

Mekanisme publikasi yang lebih aman membangun release lengkap di luar live path, memvalidasinya, lalu melakukan perpindahan yang terkendali. Desain persisnya dapat memakai direktori release, immutable image, atau maintenance window. Release berbasis symlink memerlukan perhatian tersendiri karena PHP juga memiliki realpath cache. Freshness resolusi path dan freshness opcode berkaitan secara operasional, tetapi bukan mekanisme yang sama.

Tiga model yang proporsional untuk aplikasi kecil

Model A: timestamp validation aktif, setiap request

Gunakan validate_timestamps=1 dan revalidate_freq=0, publikasikan file secara aman, lalu kirim smoke request yang representatif. Model ini mengutamakan aturan freshness yang sederhana daripada menghindari setiap pemeriksaan timestamp. Ini merupakan baseline yang masuk akal ketika traffic sederhana dan tidak ada pengukuran lokal yang menunjukkan bahwa validation adalah bottleneck berarti.

Model B: timestamp validation aktif, interval terbatas

Gunakan frekuensi revalidation positif dan terima window yang dihasilkan secara eksplisit. Verifikasi seharusnya menunggu atau mencoba kembali sesuai kebijakan tersebut, bukan mengirim satu request seketika lalu menyimpulkan bahwa release yang salah akan bertahan permanen. Intervalnya perlu menjadi keputusan operasional, bukan kejutan yang tidak terdokumentasi.

Model C: timestamp validation nonaktif, refresh dikendalikan release

Nonaktifkan validation hanya ketika setiap deployment memiliki langkah refresh yang terautentikasi dan dapat diamati untuk runtime yang melayani request. Sebuah release seharusnya berhenti aman jika langkah tersebut gagal. Model ini dapat mengurangi pemeriksaan di jalur request, tetapi mengikat correctness pada sistem release dan meningkatkan biaya ketika sistem itu dilewati untuk sebuah "edit cepat."

Tidak satu pun dari model ini selalu paling baik. Pilihan yang tepat bergantung pada workload yang diukur, disiplin deployment, freshness delay yang dapat diterima, dan seberapa mudah proses pelayanan dapat dikelola tanpa interupsi yang merugikan.

Checklist deployment yang menghasilkan bukti

  1. Catat SAPI yang melayani request, file INI yang dimuat, kebijakan timestamp, interval revalidation, dan apakah file cache aktif.
  2. Tentukan kapan kode baru diharapkan aktif berdasarkan kebijakan tersebut.
  3. Bangun dan validasi release lengkap sebelum mengeksposnya pada request.
  4. Publikasikan melalui perpindahan atomic atau prosedur maintenance eksplisit, bukan dengan menyalin urutan file live yang tidak diketahui.
  5. Jika kebijakan memerlukan invalidation, reset, atau pengelolaan proses, jalankan melalui jalur deployment yang dilindungi dan periksa hasilnya.
  6. Amati state cache atau proses dalam konteks yang melayani web, bukan hanya dari PHP CLI.
  7. Request perilaku yang berubah, path terdekat yang tidak berubah, dan failure path; periksa log aplikasi dan PHP-FPM terbaru.
  8. Simpan release sebelumnya beserta prosedur pemulihan yang telah diuji.

Version marker yang hanya tersedia melalui health check terautentikasi dapat membuat verifikasi ini lebih jelas. Marker tersebut sebaiknya mengidentifikasi artifact release, bukan mengungkap secret atau berpura-pura bahwa satu marker membuktikan semua route berfungsi. Marker menjawab "release mana yang memberi respons"; pemeriksaan perilaku menjawab apakah release tersebut bekerja.

Kesimpulan

OPcache menjadikan freshness source PHP sebagai bagian dari kontrak deployment. Dengan timestamp validation aktif, kontraknya mencakup interval revalidation. Dengan validation nonaktif, sistem release harus dengan sengaja melakukan refresh pada runtime yang relevan. Targeted invalidation, full reset, dan operasi lifecycle proses adalah tool yang berbeda, bukan mantra yang dapat dipertukarkan.

Untuk aplikasi kecil, kebijakan yang paling dapat dipertanggungjawabkan sering kali adalah kebijakan yang dapat dijelaskan dan diverifikasi dengan asumsi tersembunyi sesedikit mungkin. Optimalkan pemeriksaan timestamp hanya setelah pengukuran membenarkan dependency tambahan pada proses release. Sebelum itu, mengetahui kapan kode baru mulai aktif lebih berharga daripada membuat command pembersihan cache terlihat canggih.

References