Files
archived-frankenphp/docs/cn/performance.md
2025-08-13 20:52:42 +02:00

158 lines
6.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 性能
默认情况下FrankenPHP 尝试在性能和易用性之间提供良好的折衷。
但是,通过使用适当的配置,可以大幅提高性能。
## 线程和 Worker 数量
默认情况下FrankenPHP 启动的线程和 worker在 worker 模式下)数量是可用 CPU 数量的 2 倍。
适当的值很大程度上取决于你的应用程序是如何编写的、它做什么以及你的硬件。
我们强烈建议更改这些值。为了获得最佳的系统稳定性,建议 `num_threads` x `memory_limit` < `available_memory`
要找到正确的值,最好运行模拟真实流量的负载测试。
[k6](https://k6.io) 和 [Gatling](https://gatling.io) 是很好的工具。
要配置线程数,请使用 `php_server``php` 指令的 `num_threads` 选项。
要更改 worker 数量,请使用 `frankenphp` 指令的 `worker` 部分的 `num` 选项。
### `max_threads`
虽然准确了解你的流量情况总是更好,但现实应用往往更加
不可预测。`max_threads` [配置](config.md#caddyfile-config) 允许 FrankenPHP 在运行时自动生成额外线程,直到指定的限制。
`max_threads` 可以帮助你确定需要多少线程来处理你的流量,并可以使服务器对延迟峰值更具弹性。
如果设置为 `auto`,限制将基于你的 `php.ini` 中的 `memory_limit` 进行估算。如果无法这样做,
`auto` 将默认为 2x `num_threads`。请记住,`auto` 可能会严重低估所需的线程数。
`max_threads` 类似于 PHP FPM 的 [pm.max_children](https://www.php.net/manual/en/install.fpm.configuration.php#pm.max-children)。主要区别是 FrankenPHP 使用线程而不是
进程,并根据需要自动在不同的 worker 脚本和"经典模式"之间委派它们。
## Worker 模式
启用 [worker 模式](worker.md) 大大提高了性能,
但你的应用必须适配以兼容此模式:
你需要创建一个 worker 脚本并确保应用不会泄漏内存。
## 不要使用 musl
官方 Docker 镜像的 Alpine Linux 变体和我们提供的默认二进制文件使用 [musl libc](https://musl.libc.org)。
众所周知,当使用这个替代 C 库而不是传统的 GNU 库时PHP [更慢](https://gitlab.alpinelinux.org/alpine/aports/-/issues/14381)
特别是在以 ZTS 模式(线程安全)编译时,这是 FrankenPHP 所必需的。在大量线程环境中,差异可能很显著。
另外,[一些错误只在使用 musl 时发生](https://github.com/php/php-src/issues?q=sort%3Aupdated-desc+is%3Aissue+is%3Aopen+label%3ABug+musl)。
在生产环境中,我们建议使用链接到 glibc 的 FrankenPHP。
这可以通过使用 Debian Docker 镜像(默认)、从我们的 [Releases](https://github.com/php/frankenphp/releases) 下载 -gnu 后缀二进制文件,或通过[从源代码编译 FrankenPHP](compile.md) 来实现。
或者,我们提供使用 [mimalloc 分配器](https://github.com/microsoft/mimalloc) 编译的静态 musl 二进制文件,这缓解了线程场景中的问题。
## Go 运行时配置
FrankenPHP 是用 Go 编写的。
一般来说Go 运行时不需要任何特殊配置,但在某些情况下,
特定的配置可以提高性能。
你可能想要将 `GODEBUG` 环境变量设置为 `cgocheck=0`FrankenPHP Docker 镜像中的默认值)。
如果你在容器Docker、Kubernetes、LXC...)中运行 FrankenPHP 并限制容器的可用内存,
请将 `GOMEMLIMIT` 环境变量设置为可用内存量。
有关更多详细信息,[专门针对此主题的 Go 文档页面](https://pkg.go.dev/runtime#hdr-Environment_Variables) 是充分利用运行时的必读内容。
## `file_server`
默认情况下,`php_server` 指令自动设置文件服务器来
提供存储在根目录中的静态文件(资产)。
此功能很方便,但有成本。
要禁用它,请使用以下配置:
```caddyfile
php_server {
file_server off
}
```
## `try_files`
除了静态文件和 PHP 文件外,`php_server` 还会尝试提供你应用程序的索引
和目录索引文件(`/path/` -> `/path/index.php`)。如果你不需要目录索引,
你可以通过明确定义 `try_files` 来禁用它们,如下所示:
```caddyfile
php_server {
try_files {path} index.php
root /root/to/your/app # 在这里明确添加根目录允许更好的缓存
}
```
这可以显著减少不必要的文件操作数量。
另一种具有 0 个不必要文件系统操作的方法是改用 `php` 指令并按路径将
文件与 PHP 分开。如果你的整个应用程序由一个入口文件提供服务,这种方法效果很好。
一个在 `/assets` 文件夹后面提供静态文件的示例[配置](config.md#caddyfile-config)可能如下所示:
```caddyfile
route {
@assets {
path /assets/*
}
# /assets 后面的所有内容都由文件服务器处理
file_server @assets {
root /root/to/your/app
}
# 不在 /assets 中的所有内容都由你的索引或 worker PHP 文件处理
rewrite index.php
php {
root /root/to/your/app # 在这里明确添加根目录允许更好的缓存
}
}
```
## 占位符
你可以在 `root``env` 指令中使用[占位符](https://caddyserver.com/docs/conventions#placeholders)。
但是,这会阻止缓存这些值,并带来显著的性能成本。
如果可能,请避免在这些指令中使用占位符。
## `resolve_root_symlink`
默认情况下如果文档根目录是符号链接FrankenPHP 会自动解析它(这对于 PHP 正常工作是必要的)。
如果文档根目录不是符号链接,你可以禁用此功能。
```caddyfile
php_server {
resolve_root_symlink false
}
```
如果 `root` 指令包含[占位符](https://caddyserver.com/docs/conventions#placeholders),这将提高性能。
在其他情况下,收益将可以忽略不计。
## 日志
日志显然非常有用,但根据定义,
它需要 I/O 操作和内存分配,这会大大降低性能。
确保你[正确设置日志级别](https://caddyserver.com/docs/caddyfile/options#log)
并且只记录必要的内容。
## PHP 性能
FrankenPHP 使用官方 PHP 解释器。
所有常见的 PHP 相关性能优化都适用于 FrankenPHP。
特别是:
- 检查 [OPcache](https://www.php.net/manual/zh/book.opcache.php) 是否已安装、启用并正确配置
- 启用 [Composer 自动加载器优化](https://getcomposer.org/doc/articles/autoloader-optimization.md)
- 确保 `realpath` 缓存对于你的应用程序需求足够大
- 使用[预加载](https://www.php.net/manual/zh/opcache.preloading.php)
有关更多详细信息,请阅读[专门的 Symfony 文档条目](https://symfony.com/doc/current/performance.html)
(即使你不使用 Symfony大多数提示也很有用