- 目录
- 性能调优
性能调优¶
资源调优是深入了解以下细节之前推荐的。
重要的性能调优规则¶
- 除非您有理由更改某项设置,并且经过测试发现更改该设置对您有益,否则请优先使用 lighttpd 的默认设置。
- 正确的功能比边际性能提升更重要;一个无法按预期运行的 Web 服务器是毫无用处的。
不要为了微小的性能提升而牺牲安全性或期望的操作功能。 - 性能调优并非魔法。建议的方法是每次只进行一项更改,测试并进行基准测试,如果该更改在实际场景中没有可衡量且积极的影响,则应将其恢复。
lighttpd 通常相当灵敏。以下大部分内容都是微优化。除非您有必须解决的特定性能问题,否则无需进行任何更改。
(有关以下任何选项的详细信息,请参阅配置选项。)
lighttpd 配置性能调优(技术指南)¶
- 少即是多(而且通常也更简单)
- 在可能的情况下依赖默认值,以减少不必要的(重复的)配置处理(运行时),避免处理已设置为默认值的配置指令
- 在全局作用域中设置配置选项,而不是在子作用域中重复设置。lighttpd 会优化全局作用域中的配置设置,并使这些设置成为默认值
- TLS 配置可以在全局作用域中设置,并由多个
$SERVER["socket"]
继承
ssl.pemfile = "..."
ssl.privkey = "..."
$SERVER["socket"] == ":443" { ssl.engine = "enable" }
$SERVER["socket"] == "[::]:443" { ssl.engine = "enable" }
- 只列出在
server.modules
中实际使用和启用的模块;注释掉其他模块
- 每个加载的模块都会在 lighttpd 钩子中注册自身,并有机会处理每个请求,如果模块已加载但未配置使用,则这是不必要的
-server.compat-module-load = "disable"
跳过加载默认模块(mod_indexfile、mod_dirlisting、mod_staticfile),然后您可以显式地将一个或多个模块添加到server.modules
中以使用它们
(lighttpd 1.4.66 及更高版本如果未配置和激活,则会避免加载 mod_indexfile 和 mod_dirlisting,因此server.compat-module-load = "disable"
不再增加太多价值。) - 移除可选功能的调整
-server.tag = ""
跳过在响应中发送 "Server: lighttpd/1.4.xx";或者,使用:server.tag = "lighttpd"
来隐藏 lighttpd 版本
- 如果所有服务器响应都是小文件,可以使用server.range-requests = "disable"
,否则建议保持启用状态 - 检查您的发行版提供的默认 lighttpd 配置
- 发行版提供的配置旨在对新手友好,但可能会引入另一个配置框架的复杂性
- 发行版提供的配置通常已过时,并为了历史兼容性而保留,而不是遵循当前的最佳实践
- 示例:大约 20 年前,一些广泛使用的 Adobe Acrobat Reader 插件 PDF 客户端在范围请求方面表现不佳。
不幸的是,禁用 PDF 范围请求的配置设置自那时起已被盲目地沿用在配置中。
最好注释掉或移除:$HTTP["url"] =~ "\.pdf$" { server.range-requests = "disable" } # remove from lighttpd config
范围请求被 Adobe PDF 快速 Web 视图使用,Adobe 建议将其用于大型 PDF。
请参阅 https://helpx.adobe.com/ie/acrobat/using/optimizing-pdfs-acrobat-pro.html 底部“优化 PDF 以实现快速 Web 视图”部分 server.max-connections
限制了可处理的同时连接的最大数量,并影响连接缓存的内存使用
- 默认值约为 1365,除了最大的系统外,这对于所有其他系统来说都过大。嵌入式系统可能会设置server.max-connections = 16
或更低server.max-worker = 0
通常应保持未设置(或“0”),因为 CPU 瓶颈通常在其他地方server.follow-symlink = "enable"
(默认)应保持启用。如果需要此类限制,最好在单独的用户帐户下运行独立的 lighttpd 实例,并强制执行更严格的文件访问权限。ssl.read-ahead = "disable"
(默认)强烈推荐用于处理 TLS 数据包速度低于网络线速的较慢嵌入式系统。对于更快的系统,测试ssl.read-ahead = "enable"
是否能提高性能(或不能)- 如果不需要 h2c 并且 lighttpd 运行在代理(例如 HAProxy)后面,则禁用 h2c 支持以防止意外的 h2c 走私(安全性):
server.feature-flags += ( "server.h2c" => "disable" )
- 高分辨率时间戳在数据被使用时很有用,但它对性能和 CPU 使用会产生轻微影响,因为需要收集高分辨率时间并将其转换为字符串以进行日志记录。如果不使用这些数据,请考虑保持
server.feature-flags
中的"metrics-high-precision" => "disable"
(默认),并且不在accesslog.format
模板中使用高分辨率格式说明符。或者,在指标收集会话期间暂时启用(并重新启动 lighttpd)一段时间,评估数据,然后返回到禁用的默认设置。
- 最小化条件处理(但不要以牺牲正常功能为代价)
- 优先使用前缀 (
=^
) 或后缀 (=$
) 条件 (lighttpd 1.4.65),在这些情况下,前缀/后缀匹配可以替代简单的正则表达式条件 (=~
,!~
) - 更多条件意味着运行时需要处理更多配置
- 更多条件意味着每个请求由配置使用的内存更多
- lighttpd 1.4.62 将正则表达式使用的额外内存限制在包含%X
替换的url.redirect
或url.rewrite*
指令的条件中。
- 尽可能减少或替换%X
替换的使用,以降低每个请求的内存使用量。
- 尽可能使用 lighttpd 扩展替换模式,而不是%X
替换。
- 例如,在正则表达式替换中优先使用${url.authority}
,而不是在捕获$HTTP["host"] =~ "(.*)"
条件内使用%0
。 - 通过将条件及其相反条件合并到 if/else 中来避免重复
<condition> { ... } else { ... }
<condition> { ... } else <condition> { ... } else { ... }
- 有时,在全局作用域中设置一次配置选项,然后在必要时在少量条件下取消设置该选项,可能比在全局作用域中保留默认值并在更多条件下启用配置选项更省配置行数
- 没有配置条件的配置处理速度最快,但运行时配置处理速度很快,通常不是瓶颈
- 优先使用前缀 (
- 动态后端(mod_proxy、mod_fastcgi、mod_scgi、mod_ajp13 等)
- lighttpd 连接到同一主机上运行的后端时,优先使用 Unix 域套接字(而不是 TCP 套接字)
- lighttpd 可以监听 Unix 域套接字(
server.bind = "/path/to/lighttpd.sock"
),并且 lighttpd 的 mod_proxy 可以作为后端 lighttpd 服务器的反向代理。与 mod_extforward 一起使用以保留客户端的远程地址供后端使用。 - 对于许多动态后端(不包括 mod_proxy),会创建 CGI/1.1 环境(或等效环境)。CGI/1.1 环境包含 SERVER_ADDR。如果
server.bind = "*"
或其他通配符地址,则获取 SERVER_ADDR 需要一次getsockname()
系统调用。如果server.bind = "127.0.0.1"
或其他特定 IP 地址(不是通配符地址),则会省略该系统调用。 - 使用快速的内存文件系统作为临时文件,并提供一个大型文件系统作为备用,例如在 Linux 上:
server.upload-dirs = ("/dev/shm", "/var/tmp")
- mod_fastcgi
- 推荐:使用 PHP-FPM(FastCGI 进程管理器),它在许多操作系统发行版中都作为软件包提供
- 如果不使用 PHP-FPM,请参阅 Docs_PerformanceFastCGI- lighttpd 提供了启动 PHP 后端的机制,并且运行良好,但 PHP-FPM 是管理 PHP 后端的现代且推荐的机制
- mod_rewrite 和 mod_redirect:短路(当使用一系列正则表达式时)
- 考虑将静态文件匹配(未经修改地通过)放在前面,并使用空白目标表示不进行修改
- 考虑使用空白匹配作为全匹配,而不是 "^(.*)",后者仍会匹配所有内容,但无需正则表达式
url.rewrite-once = (
"^/static/|\.(?:css|jpg)$" => "",
"" => "/index.php${url.path}${qsa}"
)
- 如果静态文件不存在,在配置全匹配时,考虑使用
url.rewrite-if-not-file
而不是url.rewrite-once
。
上面的例子可以写成
url.rewrite-if-not-file = (
"" => "/index.php${url.path}${qsa}"
)
- mod_indexfile:如果启用了 mod_indexfile,请减少 index-file.names 中的条目数量
index-file.names = ("index.html")
作为包含一两个条目的列表,而不是包含例如 10 种不同文件扩展名的列表
- 缓存调优
- stat_cache:默认的
server.stat-cache-engine = "simple"
适用于典型用途,并缓存stat()
结果 1-2 秒
使用server.stat-cache-engine = "inotify"
或server.stat-cache-engine = "kqueue"
进行测试,以便stat()
结果缓存更长时间(16 秒) - mod_auth:设置
auth.cache = ("max-age" => "600")
以缓存密码(默认禁用),但如果启用缓存,请注意您的安全态势会发生变化。(自 lighttpd 1.4.56 起) - mod_deflate:设置
deflate.cache-dir
以基于 ETag 缓存(和重用)压缩的静态资源(自 lighttpd 1.4.56 起) - mod_dirlisting:设置
dir-listing.cache = ( ... )
以配置生成的目录列表的缓存(自 lighttpd 1.4.60 起)
- stat_cache:默认的
- 不要为了节省几个 CPU 周期而牺牲安全性
server.http-parseopts*
选项的默认值是推荐的,并且速度非常快- 禁用
server.http-parseopts*
可能会节省一些 CPU 周期,但这对于安全配置来说是一种反模式 server.http-parseopts*
选项只有在需要为网站的正常运行调整功能时才应修改- ETag 响应头用于 HTTP/1.1 条件缓存。ETag 响应头也是 mod_deflate 所必需的,并强烈建议与 mod_webdav 一起使用。虽然为了微基准测试目的可以禁用 lighttpd 对静态内容的 ETag 生成,但在生产环境中建议启用 ETag 生成(默认启用)(
etag.use-inode
、etag.use-mtime
、etag.use-size
)
- 确保
mimetype.assign
通过例如全匹配的mimetype.assign += ("" => "application/octet-stream")
为所有静态资源分配 Content-Type
如果未明确为静态资源分配 MIME 类型,lighttpd 不会随响应发送ETag
或Last-Modified
。
https://anexia.com/blog/en/the-tale-of-lighttpd-not-sending-the-last-modified-header/ - 使用 mmap 支持编译 lighttpd (
./configure --enable-mmap
) 以提高 mod_deflate 性能
利用操作系统 (OS) 功能的 lighttpd 配置¶
lighttpd 通常会为其运行的操作系统选择最佳默认值。除非出现功能不正确的情况,否则请优先使用 lighttpd 默认值。(如果 lighttpd 操作系统默认值运行不正确,请报告错误并附上您的平台信息。)server.event-handler
(例如 epoll、kqueue、event ports、devpoll、poll 等)server.network-backend
(例如 sendfile、writev、write)
针对高流量、大量连接站点的 lighttpd 配置调优¶
- 使用
server.max-fds = 16384
(或更高)进行测试,并且可能需要调整操作系统系统和/或每个用户的ulimit -Hn
以允许此值或更高值。server.max-fds
每增加 4k,lighttpd 就会额外使用约 100 kb 的内存用于内部结构,不包括每个活动连接使用的内存。(换句话说,当没有那么多同时打开的连接时,使用非常高的值会产生边际成本)。如果未配置server.max-connections
,则其计算值为server.max-fds
的 1/3。
针对低内存系统的 lighttpd 配置调优¶
- 使用
server.max-fds = 128
(或更低)进行测试 - 使用
server.max-connections = 16
(或更低)进行测试 - 使用
server.listen-backlog = 16
(或更低)进行测试 - (默认)
server.stat-cache-engine = "simple"
- (默认)
ssl.read-ahead = "disable"
- 对 HTTP/2 协议的支持(在 lighttpd 1.4.59 中默认启用)比 HTTP/1.1 使用更多的内存;
低内存系统可以选择禁用 HTTP/2 协议支持:server.feature-flags += ("server.h2proto" => "disable")
- 使用 glibc 运行的 lighttpd 将 glibc malloc
sbrk
填充配置为 512k。(glibc malloptM_TOP_PAD
的默认值为 128k。)
对于 lighttpd 1.4.68 及更高版本,如果server.max-connections = 16
(或更低),则sbrk
填充设置为 128k。
在启动 lighttpd 之前在环境中导出环境变量MALLOC_TOP_PAD_=131072
,以便获得与其他配置类似的行为。 - lighttpd mod_dirlisting
dir-listing.sort = "disable"
(自 1.4.74 起)可以减少生成目录列表所用的内存,这对于大型目录可能很有用。dir-listing.sort = "disable"
可以与server.stream-response-body = 2
一起使用,以便在临时文件指向 tmpfs(内存中)文件系统时进一步减少内存使用,例如当server.upload-dirs = ("/tmp")
且/tmp
是 tmpfs 时。在微型、资源受限的系统上,使用 mod_indexfile 代替 mod_dirlisting 甚至更高效,前提是您有一个带外进程在目录更改时更新index.html
。
反向代理后 lighttpd 的配置调优¶
- 对于 HAProxy 或支持 HAProxy PROXY 协议的负载均衡器后面的 lighttpd 实例,优先配置 mod_extforward 的
extforward.hap-PROXY
- 一些反向代理可能配置为对多个客户端重用同一个 HTTP/2 连接
针对流量整形(下载速率限制)的 lighttpd 配置调优¶
流量整形connection.kbytes-per-second
server.kbytes-per-second
针对超时设置的 lighttpd 配置调优¶
为了更快地释放连接,请调低空闲超时设置,包括 lighttpd 等待从客户端读取或写入数据的时间(当 lighttpd 正在尝试读取或写入时),以及 lighttpd 等待下一个 Keep-Alive 请求的时间和 Keep-Alive 请求的数量,之后 lighttpd 会关闭连接。值为 0 会禁用空闲超时,不建议这样做。server.max-read-idle = 60
server.max-write-idle = 360
server.max-keep-alive-idle = 5
server.max-keep-alive-requests = 1000
(lighttpd 1.4.65 默认 1000;lighttpd 1.4.46 - lighttpd 1.4.64 默认 100;lighttpd 1.4.46 之前默认 10)
通常,不应将 server.max-keep-alive-requests
设置为 0,因为建立新的 TCP 连接比保持一个空闲的 fd 打开需要更多的资源,尤其是在连接通过 TLS 进行时。
针对基准测试的 lighttpd 配置调优¶
在考虑将这些设置用于基准测试环境之外时,请务必理解每项设置。这些设置可能不适用于生产环境。
- 基准测试:调优 Linux TCP 堆栈
临时设置会立即生效并在重启后重置为默认值。
/sbin/sysctl net.ipv4.tcp_fin_timeout=1
/sbin/sysctl net.ipv4.tcp_low_latency=1
/sbin/sysctl net.ipv4.tcp_slow_start_after_idle=0
/sbin/sysctl net.ipv4.tcp_tw_reuse=1
- 基准测试:调优 Linux CPU 频率缩放
记下当前的电源设置,例如:
cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
powersave
powersave
临时设置会立即生效并在重启后重置为默认值。
echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor >/dev/null
cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
performance
performance
其他参考:https://wiki.archlinux.org.cn/title/CPU_frequency_scaling
- 基准测试:减少其他操作系统和硬件的基准测试噪声源
在基准测试期间关闭或暂停其他 CPU 和内存密集型进程。不要忽略关闭您的图形用户界面(GUI)网页浏览器!
CPU 亲和性:考虑使用taskset
将进程固定到特定的 CPU 或 CPU 集。
禁用 ASLR (setarch -R <cmd>
)
禁用 CPU 动态频率缩放和 CPU 超线程(通常在 BIOS/UEFI 中配置)
- 基准测试:调优 Linux CPU 漏洞缓解措施
通过在启动时暂时将mitigations=off
添加到内核命令行,临时禁用 Spectre、Meltdown 和其他 CPU 漏洞缓解措施。
警告:禁用缓解措施通常不适用于生产环境。
https://linuxkernel.org.cn/doc/html/latest/admin-guide/kernel-parameters.html 并在此文档中搜索 "mitigations="
CPU 漏洞缓解措施可以将基准测试性能降低约 25%-40%,但强烈建议在生产系统中启用 CPU 漏洞缓解措施。一个被攻破的系统可能比一个宕机的系统更糟糕。优先选择安全且健壮的系统。(不过,基准测试结果中惊人的数字确实很有趣!)
平台特定说明¶
注意:以下内容已旧且可能已过时。请仅将其视为进一步测试的起点。
Linux¶
禁用 TCP 选项可以减少每个 TCP 数据包的开销,并且可能
有助于从服务器榨取最后几个百分点的性能。请注意,
禁用这些选项很可能会降低高延迟和高丢包
链路的性能。
- net.ipv4.tcp_sack = 0
- net.ipv4.tcp_timestamps = 0
注意:请谨慎使用 net.ipv4.tcp_timestamps。在高并发连接的基准测试负载下,它给我带来了巨大的问题。
增加 TCP 发送和接收缓冲区将极大地提高性能,
前提是(并且仅当)您有大量大文件要发送。
- net.ipv4.tcp_wmem = 4096 65536 524288
- net.core.wmem_max = 1048576
如果您有大量大文件上传,增加接收缓冲区会有所帮助。
- net.ipv4.tcp_rmem = 4096 87380 524288
- net.core.rmem_max = 1048576
高流量站点发现的一些有用事项
# These ensure that TIME_WAIT ports either get reused or closed fast. net.ipv4.tcp_fin_timeout = 1 net.ipv4.tcp_tw_recycle = 1 # TCP memory net.core.rmem_max = 16777216 net.core.rmem_default = 16777216 net.core.netdev_max_backlog = 262144 net.core.somaxconn = 262144 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_orphans = 262144 net.ipv4.tcp_max_syn_backlog = 262144 net.ipv4.tcp_synack_retries = 2 net.ipv4.tcp_syn_retries = 2 # you shouldn't be using conntrack on a heavily loaded server anyway, but these are # suitably high for our uses, insuring that if conntrack gets turned on, the box doesn't die net.ipv4.netfilter.ip_conntrack_max = 1048576 net.nf_conntrack_max = 1048576
请记住,每个 TCP 连接都会使用为套接字配置的内存量。
缓冲区。如果您有大量连接,这会很快耗尽可用内存。
有关这些参数的更多信息,请参阅 http://www.acc.umu.se/~maswan/linux-netperf.txt。
FreeBSD¶
在 FreeBSD 上,通过启用接受过滤器,您可能会获得一些性能提升。只需
使用以下方式编译内核:
options ACCEPT_FILTER_HTTP
或者直接使用以下方式加载:
kldload accf_http
有关调优 FreeBSD 的更多想法,请阅读:tuning(7)
如果服务器只处理 HTTP
请求,没有大量上传,那么减少 recvspace 通常是可以的。增加 sendspace 会减少
系统负载,如果您有大量大文件要发送,但请记住
您必须为每个连接在内核中提供内存。1024 * 64KB
将意味着 64MB 的内核 RAM。请牢记这一点。
- net.inet.tcp.recvspace = 4096