PHP 8.2'de opcache ve gerçek trafikte bellek taşması

这篇内容暂时只有 Türkçe 版本,以下是原文。

Geçen ay 8.2.14’e geçtikten sonra üretimde bir sorun çıktı: 12 çekirdekli, 32 GB RAM’li iki web sunucusunda php-fpm çocukları 40-60 dakika içinde max_execution_time’a takılmadan yavaşça şişiyordu. Trafik 1200 rps civarı, uygulama Laravel değil, kendi yazdığımız bir routing katmanı var ve günlük yaklaşık 3 milyon istek alıyor.

Önce opcache’ı kapattık, sorun kayboldu. Yani mesele opcache’ta. Ama tamamen kapatmak 8.2’de ciddi CPU artışı demek; bizde yüzde 18 civarı. Şu ayarlarla denedik:

opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=40000
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.save_comments=0
opcache.file_cache=/var/cache/php/opcache
opcache.file_cache_only=0

file_cache eklemek işe yaradı: opcache dolduğunda shared memory’den değil diskteki kopyadan okuyor, yeniden derleme sırasında çocuk süreçlerin RSS’i sabit kalıyor. max_accelerated_files 40000’e çekmeden önce opcache_get_status() çıktısında num_cached_scripts 39000 küsürde takılıydı ve neredeyse her istekte yeniden derleme oluyordu. Bunu opcache_get_status(false)['opcache_statistics'] üzerinden izledik.

Mekanizma şu: opcache dolduğunda FIFO değil, daha karmaşık bir tahliye var; sık kullanılan dosyalar kalıyor ama tek seferlik dosyalar sürekli derleniyor. file_cache açıkken derleme maliyeti diske kayıyor, süreç belleği şişmiyor. Bedeli: ilk istekte disk okuması, ve dağıtımda opcache_reset() çağırmak yerine dosya önbelleğini de temizlemek gerekiyor. Biz deploy script’inde find /var/cache/php/opcache -type f -delete çalıştırıyoruz, yoksa eski dosyalar kalıyor.

Nerede işe yaramaz: file_cache NFS üzerinde çalışmıyor, bizim bir staging makinesinde tam bu yüzden sessizce devre dışı kaldı ve sorun tekrar etti. Ayrıca save_comments=0 ile bazı attribute tabanlı kütüphaneler (doctrine/annotations gibi) çalışma anında patlıyor; bizde bir cron job bunu fark etti ama üretimde olsaydı gece yarısı sürpriz olurdu. Bir de opcache.file_cache_only=1 yapıp shared memory’yi tamamen kapatmayı denedik, o zaman da her istekte disk I/O arttı ve p99 40 ms yükseldi.

Şu an iki sunucuda RSS 250 MB bandında sabit. Sizin kurulumunuzda file_cache kullanıyor musunuz, yoksa sadece memory_consumption’ı büyütüp geçiyor musunuz?

0
赞同度 100% · 0 条评论 · 4 阅读

0 条评论

支持 Markdown · 回复会实时推送给对方

还没有评论,写下第一条。