OPcache 优化策略
概述
仅仅启用 OPcache 并不足以发挥其最大价值。在生产环境中,通过合理的缓存预热、命中率监控、缓存失效处理等优化策略,可以显著提升 PHP 应用的响应速度和稳定性。本章将深入探讨 OPcache 的优化方法,帮助你在各种场景下获得最佳性能表现。
前置知识
阅读本节前,建议先了解:OPcache 配置详解
基础概念
缓存命中率
缓存命中率(Hit Rate)是衡量 OPcache 效果的核心指标:
命中率 = 缓存命中次数 / (缓存命中次数 + 缓存未命中次数) × 100%一个健康的生产环境应保持 95% 以上的命中率。低于 95% 通常意味着配置不当或频繁的缓存失效。
缓存失效场景
OPcache 缓存会在以下情况失效:
- 文件修改:PHP 文件内容发生变化(
validate_timestamps = 1时) - 手动清除:调用
opcache_reset()或opcache_invalidate() - 内存溢出:共享内存不足,旧缓存被淘汰
- 进程重启:PHP-FPM 重启或重新加载
缓存预热
缓存预热(Warmup)是在应用启动或部署后,提前将关键 PHP 文件编译并缓存到 OPcache 中,避免用户首次请求时的编译延迟。
详细说明
缓存命中率监控
opcache_get_status() 详解
php
<?php
declare(strict_types=1);
/**
* 获取 OPcache 完整状态信息
*/
function getOpcacheDetailedStatus(): array
{
$status = opcache_get_status(false);
if ($status === false) {
throw new RuntimeException('OPcache 未启用');
}
return [
// 缓存统计
'hit_rate' => $status['opcache_statistics']['opcache_hit_rate'],
'hits' => $status['opcache_statistics']['hits'],
'misses' => $status['opcache_statistics']['misses'],
'num_cached_scripts' => $status['opcache_statistics']['num_cached_scripts'],
'num_cached_keys' => $status['opcache_statistics']['num_cached_keys'],
'max_cached_keys' => $status['opcache_statistics']['max_cached_keys'],
// 内存统计
'used_memory' => $status['memory_usage']['used_memory'],
'free_memory' => $status['memory_usage']['free_memory'],
'wasted_memory' => $status['memory_usage']['wasted_memory'],
'total_memory' => $status['memory_usage']['used_memory']
+ $status['memory_usage']['free_memory'],
// 重启统计
'oom_restarts' => $status['opcache_statistics']['oom_restarts'],
'hash_restarts' => $status['opcache_statistics']['hash_restarts'],
'manual_restarts' => $status['opcache_statistics']['manual_restarts'],
// JIT 统计
'jit' => $status['jit'] ?? null,
];
}
$status = getOpcacheDetailedStatus();
echo "命中率: {$status['hit_rate']}%" . PHP_EOL;
echo "已缓存脚本: {$status['num_cached_scripts']}" . PHP_EOL;
echo "OOM 重启: {$status['oom_restarts']}" . PHP_EOL;命中率阈值告警
php
<?php
declare(strict_types=1);
/**
* OPcache 健康检查类
*/
class OpcacheHealthChecker
{
private const WARN_HIT_RATE = 95.0;
private const CRITICAL_HIT_RATE = 90.0;
private const WARN_MEMORY_USAGE = 80.0;
private const CRITICAL_MEMORY_USAGE = 95.0;
public function check(): array
{
$status = opcache_get_status(false);
if ($status === false) {
return [
'status' => 'critical',
'message' => 'OPcache 未启用',
];
}
$stats = $status['opcache_statistics'];
$mem = $status['memory_usage'];
$issues = [];
// 检查命中率
$hitRate = (float) $stats['opcache_hit_rate'];
if ($hitRate < self::CRITICAL_HIT_RATE) {
$issues[] = [
'level' => 'critical',
'message' => sprintf(
'命中率 %.2f%% 低于临界值 %.1f%%',
$hitRate,
self::CRITICAL_HIT_RATE
),
];
} elseif ($hitRate < self::WARN_HIT_RATE) {
$issues[] = [
'level' => 'warning',
'message' => sprintf(
'命中率 %.2f%% 低于警告值 %.1f%%',
$hitRate,
self::WARN_HIT_RATE
),
];
}
// 检查内存使用率
$totalMem = $mem['used_memory'] + $mem['free_memory'];
$usedPercent = ($mem['used_memory'] / $totalMem) * 100;
if ($usedPercent > self::CRITICAL_MEMORY_USAGE) {
$issues[] = [
'level' => 'critical',
'message' => sprintf(
'内存使用率 %.1f%% 超过临界值 %.1f%%',
$usedPercent,
self::CRITICAL_MEMORY_USAGE
),
];
} elseif ($usedPercent > self::WARN_MEMORY_USAGE) {
$issues[] = [
'level' => 'warning',
'message' => sprintf(
'内存使用率 %.1f%% 超过警告值 %.1f%%',
$usedPercent,
self::WARN_MEMORY_USAGE
),
];
}
// 检查 OOM 重启
if ($stats['oom_restarts'] > 0) {
$issues[] = [
'level' => 'critical',
'message' => "内存溢出重启 {$stats['oom_restarts']} 次",
];
}
// 检查哈希表重启
if ($stats['hash_restarts'] > 0) {
$issues[] = [
'level' => 'warning',
'message' => "哈希表溢出重启 {$stats['hash_restarts']} 次",
];
}
return [
'status' => empty($issues) ? 'healthy' : 'unhealthy',
'hit_rate' => $hitRate,
'memory_usage_percent' => round($usedPercent, 2),
'issues' => $issues,
];
}
}缓存失效处理
opcache_invalidate() 使用
php
<?php
declare(strict_types=1);
/**
* 文件更新后精确失效 OPcache 缓存
*/
function invalidateFileCache(string $filePath): bool
{
// 检查文件是否存在
if (!file_exists($filePath)) {
return false;
}
// 强制失效该文件的缓存(即使 validate_timestamps=0 也能工作)
return opcache_invalidate($filePath, true);
}
/**
* 批量失效缓存(部署时使用)
*/
function invalidateDirectoryCache(string $directory, bool $force = true): int
{
$count = 0;
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(
$directory,
RecursiveDirectoryIterator::SKIP_DOTS
)
);
foreach ($iterator as $file) {
/** @var SplFileInfo $file */
if ($file->isFile() && $file->getExtension() === 'php') {
if (opcache_invalidate($file->getPathname(), $force)) {
$count++;
}
}
}
return $count;
}
// 使用示例:更新单个文件后
invalidateFileCache('/var/www/html/app/Services/UserService.php');
// 使用示例:部署新版本后批量失效
$invalidated = invalidateDirectoryCache('/var/www/html/app', true);
echo "已失效 {$invalidated} 个文件的缓存" . PHP_EOL;opcache_reset() 使用
php
<?php
declare(strict_types=1);
/**
* 重置所有 OPcache 缓存
* 注意:这会影响所有 PHP 进程
*/
function resetAllCache(): void
{
if (!opcache_reset()) {
throw new RuntimeException('OPcache 重置失败');
}
echo "所有 OPcache 缓存已重置" . PHP_EOL;
}
::: danger opcache_reset 的代价
`opcache_reset()` 会清除所有缓存,之后所有请求都需要重新编译。在生产环境中应谨慎使用,优先考虑 `opcache_invalidate()` 进行精确失效。
:::部署集成失效
php
<?php
declare(strict_types=1);
/**
* 部署后的缓存管理器
*/
class DeploymentCacheManager
{
public function __construct(
private string $projectRoot,
private array $watchedDirs = [],
) {
}
/**
* 部署后刷新缓存
*/
public function refreshAfterDeploy(): void
{
echo "开始部署后缓存刷新..." . PHP_EOL;
// 策略1:仅刷新变更的文件
$changedFiles = $this->getChangedFiles();
foreach ($changedFiles as $file) {
opcache_invalidate($file, true);
echo "失效: {$file}" . PHP_EOL;
}
// 策略2:如果 validate_timestamps=0,需要刷新所有 watched 目录
if (ini_get('opcache.validate_timestamps') === '0') {
foreach ($this->watchedDirs as $dir) {
$fullPath = $this->projectRoot . '/' . $dir;
if (is_dir($fullPath)) {
$this->invalidateDirectory($fullPath);
}
}
}
// 策略3:预热关键文件
$this->warmupCriticalFiles();
echo "缓存刷新完成" . PHP_EOL;
}
private function getChangedFiles(): array
{
// 可与 Git 结合获取变更文件列表
// 此处为简化示例
return [];
}
private function invalidateDirectory(string $dir): void
{
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS)
);
foreach ($iterator as $file) {
/** @var SplFileInfo $file */
if ($file->isFile() && $file->getExtension() === 'php') {
opcache_invalidate($file->getPathname(), true);
}
}
}
private function warmupCriticalFiles(): void
{
// 预热入口文件和常用服务
$criticalFiles = [
$this->projectRoot . '/public/index.php',
$this->projectRoot . '/app/Providers/AppServiceProvider.php',
];
foreach ($criticalFiles as $file) {
if (file_exists($file)) {
opcache_compile_file($file);
}
}
}
}缓存预热策略
按需预热
php
<?php
declare(strict_types=1);
/**
* 智能缓存预热器
* 优先预热访问频率最高的文件
*/
class SmartCacheWarmer
{
/**
* 基于访问日志预热
*/
public function warmupByAccessLog(string $logFile, string $docRoot, int $limit = 100): array
{
$fileAccessCount = [];
$handle = fopen($logFile, 'r');
if ($handle === false) {
throw new RuntimeException("无法打开日志文件: {$logFile}");
}
while (($line = fgets($handle)) !== false) {
// 解析 Nginx/Apache 访问日志获取 PHP 文件路径
if (preg_match('/GET\s+(\S+\.php)\s/', $line, $matches)) {
$path = $matches[1];
$fileAccessCount[$path] = ($fileAccessCount[$path] ?? 0) + 1;
}
}
fclose($handle);
// 按访问频率排序
arsort($fileAccessCount);
$topFiles = array_slice(array_keys($fileAccessCount), 0, $limit);
// 预热文件
$results = ['success' => 0, 'failed' => 0];
foreach ($topFiles as $path) {
$fullPath = $docRoot . $path;
if (file_exists($fullPath)) {
if (opcache_compile_file($fullPath)) {
$results['success']++;
} else {
$results['failed']++;
}
}
}
return $results;
}
/**
* 基于 Composer autoload 预热
*/
public function warmupByAutoload(string $vendorDir): int
{
$count = 0;
$classMapFile = $vendorDir . '/composer/autoload_classmap.php';
if (!file_exists($classMapFile)) {
// 如果没有 classmap,生成一个
exec("cd {$vendorDir}/.. && composer dump-autoload --optimize");
}
// 加载 classmap
$classMap = require $classMapFile;
foreach ($classMap as $class => $file) {
if (file_exists($file) && opcache_compile_file($file)) {
$count++;
}
}
return $count;
}
}预热 Web 界面(管理面板)
php
<?php
declare(strict_types=1);
/**
* OPcache 管理接口
* 注意:生产环境必须加访问控制!
*/
class OpcacheAdminController
{
/**
* 获取缓存状态(API 接口)
*/
public function status(): array
{
$this->ensureCliOrAdmin();
$status = opcache_get_status(false);
return [
'enabled' => $status !== false,
'memory' => $status['memory_usage'] ?? null,
'statistics' => $status['opcache_statistics'] ?? null,
'jit' => $status['jit'] ?? null,
'config' => $this->getConfig(),
];
}
/**
* 失效单个文件
*/
public function invalidate(string $file): bool
{
$this->ensureCliOrAdmin();
$fullPath = $this->resolvePath($file);
return opcache_invalidate($fullPath, true);
}
/**
* 重置所有缓存
*/
public function reset(): void
{
$this->ensureCliOrAdmin();
if (PHP_SAPI !== 'cli') {
opcache_reset();
echo "OPcache 已重置" . PHP_EOL;
}
}
/**
* 获取所有已缓存的脚本列表
*/
public function cachedScripts(): array
{
$this->ensureCliOrAdmin();
$status = opcache_get_status(false);
return $status['opcache_statistics']['cached_scripts'] ?? [];
}
private function ensureCliOrAdmin(): void
{
if (PHP_SAPI === 'cli') {
return;
}
// 这里应加入实际的权限验证逻辑
// 例如检查 IP 白名单、Admin Token 等
}
private function resolvePath(string $relativePath): string
{
$realpath = realpath($relativePath);
if ($realpath === false) {
throw new InvalidArgumentException("文件不存在: {$relativePath}");
}
return $realpath;
}
private function getConfig(): array
{
$directives = [
'opcache.enable',
'opcache.memory_consumption',
'opcache.interned_strings_buffer',
'opcache.max_accelerated_files',
'opcache.validate_timestamps',
'opcache.save_comments',
'opcache.jit',
'opcache.jit_buffer_size',
];
$config = [];
foreach ($directives as $dir) {
$config[$dir] = ini_get($dir);
}
return $config;
}
}生产环境最佳配置
完整优化配置
ini
; /etc/php/8.1/fpm/conf.d/99-opcache-production.ini
[OPcache]
; === 基本开关 ===
opcache.enable = 1
opcache.enable_cli = 0
opcache.enable_dl = 0
; === 内存配置 ===
; 操作码缓存内存:根据项目实际需求调整
opcache.memory_consumption = 512
; 内部字符串缓冲区
opcache.interned_strings_buffer = 32
; 最大缓存文件数
opcache.max_accelerated_files = 40000
; === 缓存验证 ===
; 生产环境关闭时间戳验证(提升 5-15% 性能)
opcache.validate_timestamps = 0
opcache.revalidate_freq = 0
; === 代码优化 ===
; 启用所有优化
opcache.optimization_level = 0x7FFFBFFF
; 保留注释(框架依赖)
opcache.save_comments = 1
; 快速关闭
opcache.fast_shutdown = 1
; === 文件缓存 ===
; 启用磁盘缓存,加速 PHP-FPM 重启后的首次请求
opcache.file_cache = /var/cache/php/opcache
opcache.file_cache_only = 0
; 启用一致性检查
opcache.file_cache_consistency_checks = 1
; === JIT ===
; 使用 tracing 模式获得最佳性能
opcache.jit = 1254
opcache.jit_buffer_size = 256M
; === 保护 ===
; 黑名单
opcache.blacklist_filename = /etc/php/opcache-blacklist.txt
; 禁止超大文件缓存(保护内存)
opcache.max_file_size = 0
; 保护模式(限制 opcache_* 函数在脚本中调用)
; opcache.restrict_api = /var/www/html/admin/FPM 进程池整合
ini
; /etc/php/8.1/fpm/pool.d/www.conf 中整合 OPcache 管理
; 使用 ondemand PM 时注意 OPcache 预热
; dynamic PM 通常更适合 OPcache 场景
[www]
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 20
pm.max_requests = 500
; OPcache 预热脚本(FPM 启动时执行)
; php-fpm 本身不支持 preload,但可以通过 systemd ExecStartPost 实现systemd 服务集成预热
ini
# /etc/systemd/system/php8.1-fpm.service.d/opcache-warmup.conf
[Service]
# FPM 启动后执行预热
ExecStartPost=/usr/bin/php /var/www/html/scripts/opcache-warmup.php实战示例
Nginx + PHP-FPM 负载测试对比
php
<?php
declare(strict_types=1);
/**
* 性能基准测试脚本
* 用于对比 OPcache 启用前后的性能差异
*/
class OpcacheBenchmark
{
private int $iterations;
private string $targetUrl;
public function __construct(string $targetUrl, int $iterations = 100)
{
$this->targetUrl = $targetUrl;
$this->iterations = $iterations;
}
/**
* 使用 curl_multi 并发测试
*/
public function run(): array
{
$times = [];
$mh = curl_multi_init();
// 分批处理避免资源耗尽
$batchSize = 10;
for ($i = 0; $i < $this->iterations; $i += $batchSize) {
$handles = [];
for ($j = 0; $j < $batchSize && ($i + $j) < $this->iterations; $j++) {
$ch = curl_init($this->targetUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, false);
curl_multi_add_handle($mh, $ch);
$handles[] = $ch;
}
// 等待所有请求完成
do {
$status = curl_multi_exec($mh, $active);
} while ($status === CURLM_CALL_MULTI_PERFORM && $active);
// 收集结果
foreach ($handles as $ch) {
$info = curl_getinfo($ch);
$times[] = $info['total_time'];
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
}
curl_multi_close($mh);
return $this->analyzeResults($times);
}
private function analyzeResults(array $times): array
{
sort($times);
$count = count($times);
$sum = array_sum($times);
return [
'total_requests' => $count,
'avg' => round($sum / $count * 1000, 2) . 'ms',
'min' => round(min($times) * 1000, 2) . 'ms',
'max' => round(max($times) * 1000, 2) . 'ms',
'p50' => round($times[(int) ($count * 0.50)] * 1000, 2) . 'ms',
'p90' => round($times[(int) ($count * 0.90)] * 1000, 2) . 'ms',
'p99' => round($times[(int) ($count * 0.99)] * 1000, 2) . 'ms',
'rps' => round($count / $sum, 2),
];
}
}
// 使用示例
$benchmark = new OpcacheBenchmark('http://localhost/api/test', 200);
$results = $benchmark->run();
echo "=== OPcache 性能基准测试 ===" . PHP_EOL;
foreach ($results as $metric => $value) {
echo " {$metric}: {$value}" . PHP_EOL;
}Grafana 监控指标导出
php
<?php
declare(strict_types=1);
/**
* Prometheus 格式的 OPcache 监控指标导出
* 可集成到 Prometheus + Grafana 监控系统
*/
class OpcacheMetricsExporter
{
/**
* 导出 Prometheus 格式指标
*/
public function export(): string
{
$status = opcache_get_status(false);
if ($status === false) {
return '# OPcache is disabled';
}
$stats = $status['opcache_statistics'];
$mem = $status['memory_usage'];
$metrics = [];
// 缓存命中率
$metrics[] = $this->gauge(
'opcache_hit_rate_percent',
(float) $stats['opcache_hit_rate']
);
// 内存指标
$metrics[] = $this->gauge(
'opcache_memory_used_bytes',
$mem['used_memory']
);
$metrics[] = $this->gauge(
'opcache_memory_free_bytes',
$mem['free_memory']
);
$metrics[] = $this->gauge(
'opcache_memory_wasted_bytes',
$mem['wasted_memory'] ?? 0
);
// 缓存数量
$metrics[] = $this->gauge(
'opcache_num_cached_scripts',
$stats['num_cached_scripts']
);
$metrics[] = $this->gauge(
'opcache_num_cached_keys',
$stats['num_cached_keys']
);
// 重启次数
$metrics[] = $this->gauge(
'opcache_oom_restarts_total',
$stats['oom_restarts']
);
$metrics[] = $this->gauge(
'opcache_hash_restarts_total',
$stats['hash_restarts']
);
// 命中/未命中计数
$metrics[] = $this->gauge(
'opcache_hits_total',
$stats['hits']
);
$metrics[] = $this->gauge(
'opcache_misses_total',
$stats['misses']
);
return implode("\n", $metrics) . "\n";
}
private function gauge(string $name, int|float $value): string
{
return "opcache_{$name} {$value}";
}
}
// HTTP 端点导出
if (PHP_SAPI === 'cli' || (isset($_GET['metrics']) && $_SERVER['REMOTE_ADDR'] === '127.0.0.1')) {
header('Content-Type: text/plain; version=0.0.4; charset=utf-8');
$exporter = new OpcacheMetricsExporter();
echo $exporter->export();
}注意事项
常见陷阱
冷启动问题:PHP-FPM 重启后缓存为空,首次请求延迟高。通过文件缓存和预热脚本解决。
validate_timestamps 的误解:在
opcache.enable_cli = 0时,CLI 脚本中的 OPcache 操作不会影响 FPM 进程。opcache_invalidate 不会触发重新编译:该函数仅标记缓存为无效,下次请求时才会重新编译。
多 PHP-FPM pool 的内存隔离:每个 pool 有独立的 PHP 进程组,但共享同一块 OPcache 共享内存。
故障排查
php
<?php
declare(strict_types=1);
/**
* OPcache 故障排查工具
*/
class OpcacheTroubleshooter
{
public function run(): void
{
echo "=== OPcache 故障排查 ===" . PHP_EOL . PHP_EOL;
// 1. 检查扩展是否加载
$this->checkExtensionLoaded();
// 2. 检查配置
$this->checkConfiguration();
// 3. 检查内存
$this->checkMemory();
// 4. 检查文件缓存
$this->checkFileCache();
// 5. 检查 JIT
$this->checkJit();
}
private function checkExtensionLoaded(): void
{
echo "1. 扩展检查" . PHP_EOL;
echo " OPcache 已加载: " . (extension_loaded('Zend OPcache') ? '是' : '否') . PHP_EOL;
echo " SAPI: " . PHP_SAPI . PHP_EOL;
echo " PHP 版本: " . PHP_VERSION . PHP_EOL;
echo PHP_EOL;
}
private function checkConfiguration(): void
{
echo "2. 配置检查" . PHP_EOL;
$checks = [
['opcache.enable', '1', 'OPcache 必须启用'],
['opcache.save_comments', '1', '注释保存应启用'],
];
foreach ($checks as [$key, $expected, $desc]) {
$actual = ini_get($key);
$status = ($actual === $expected) ? 'OK' : '检查';
echo " [{$status}] {$key} = {$actual} (期望: {$expected}) - {$desc}" . PHP_EOL;
}
// 环境相关检查
if (PHP_SAPI === 'fpm') {
$ts = ini_get('opcache.validate_timestamps');
if ($ts === '1') {
echo " [WARN] validate_timestamps=1 在 FPM 中会增加开销" . PHP_EOL;
}
}
echo PHP_EOL;
}
private function checkMemory(): void
{
echo "3. 内存检查" . PHP_EOL;
$status = opcache_get_status(false);
if ($status === false) {
echo " OPcache 未启用,跳过" . PHP_EOL;
return;
}
$mem = $status['memory_usage'];
$totalMB = ($mem['used_memory'] + $mem['free_memory']) / 1024 / 1024;
$usedMB = $mem['used_memory'] / 1024 / 1024;
$usedPercent = ($mem['used_memory'] / ($mem['used_memory'] + $mem['free_memory'])) * 100;
echo " 总内存: " . round($totalMB, 2) . "MB" . PHP_EOL;
echo " 已使用: " . round($usedMB, 2) . "MB ({$usedPercent}%)" . PHP_EOL;
if (isset($mem['wasted_memory']) && $mem['wasted_memory'] > 0) {
echo " 浪费: " . round($mem['wasted_memory'] / 1024 / 1024, 2) . "MB" . PHP_EOL;
}
$stats = $status['opcache_statistics'];
if ($stats['oom_restarts'] > 0) {
echo " [CRITICAL] OOM 重启: {$stats['oom_restarts']} 次" . PHP_EOL;
}
echo PHP_EOL;
}
private function checkFileCache(): void
{
echo "4. 文件缓存检查" . PHP_EOL;
$fileCache = ini_get('opcache.file_cache');
echo " 文件缓存目录: " . ($fileCache ?: '未启用') . PHP_EOL;
if ($fileCache && is_dir($fileCache)) {
echo " 目录存在: 是" . PHP_EOL;
echo " 目录可写: " . (is_writable($fileCache) ? '是' : '否') . PHP_EOL;
}
echo PHP_EOL;
}
private function checkJit(): void
{
echo "5. JIT 检查" . PHP_EOL;
$jit = ini_get('opcache.jit');
$jitBuffer = ini_get('opcache.jit_buffer_size');
echo " JIT 模式: {$jit}" . PHP_EOL;
echo " JIT 缓冲区: {$jitBuffer}" . PHP_EOL;
}
}
if (PHP_SAPI === 'cli') {
$troubleshooter = new OpcacheTroubleshooter();
$troubleshooter->run();
}最佳实践
1. 部署流程最佳实践
1. 代码合并到生产分支
2. 运行测试套件
3. 部署代码到服务器
4. 运行 opcache_compile_file 预热关键文件
5. 验证应用健康状态
6. 监控命中率回归2. 监控集成
- 将
opcache_get_status()数据接入 Prometheus/Grafana - 设置命中率告警阈值:低于 95% Warning,低于 90% Critical
- 监控
oom_restarts和hash_restarts计数器
3. 容量规划
- 使用
opcache.file_cache持久化缓存,加速重启 - 共享内存至少预留 30% 余量
- 在流量高峰前执行缓存预热
4. 安全考虑
- 使用
opcache.restrict_api限制管理功能调用路径 - 管理接口添加 IP 白名单和 Token 认证
- 定期审计 OPcache 配置
下一节
继续学习:JIT 编译器