我正在运行一个带有多个虚拟主机的 apache2 服务器。我在资源相当受限的 Raspberry Pi 4 上运行它。特别是 RAM 非常紧张(4GB)。流量并不多,我主要用它来托管 nextcloud、自定义流媒体网站和一些静态文件。
问题在于静态文件。每当我或其他任何人下载文件时,似乎整个文件都加载到了 RAM 中。对于小文件来说这不是问题,但任何大于 500MB 的文件都会引起严重问题,通常会填满 SWAP 并最终导致 Apache 的 OOM 终止。
我无论如何也想不出如何让它简单地从磁盘流式传输文件,而不是在发送之前将它们缓存在内存中。如果你在一台合适的服务器上有 128GB 的 RAM,这可能是可行的,但它在我可怜的 PI 上让我很头疼。
那么我该如何让 apache 只从磁盘流式传输文件?而且它为什么要将文件加载到 RAM 中?磁盘 i/o 比网络快得多,因此将文件从磁盘缓存到内存是没有意义的。
我尝试过:
- 从 mpm_prefetch 切换到 mpm_event。
EnableSendfile On
,似乎什么也没做。- mod_xsendfile 具有
XSendFile On
- 寻找其他解决方案,包括
如果可能的话,我希望避免对 nginx 托管文件进行反向代理,因为那只会增加一切的复杂性。
我的一个虚拟主机存在此问题:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName host.tld
ServerAdmin [email protected]
DocumentRoot /var/www/web
CustomLog ${APACHE_LOG_DIR}/access.log combined
# Generate more pleasing and modern looking listing
IndexOptions FancyIndexing IconsAreLinks FoldersFirst
EnableSendfile On
EnableMMAP Off
<IfModule mod_xsendfile.c>
<Directory "/var/www/web">
XSendFile On
XSendFilePath /var/www/web
</Directory>
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^/\.well-known/carddav /nextcloud/remote.php/dav [R=301,L]
RewriteRule ^/\.well-known/caldav /nextcloud/remote.php/dav [R=301,L]
RewriteRule ^/\.well-known/webfinger /nextcloud/index.php/.well-known/webfinger [R=301,L]
RewriteRule ^/\.well-known/nodeinfo /nextcloud/index.php/.well-known/nodeinfo [R=301,L]
RewriteRule ^/ocm-provider/?$ index.php [QSA,L]
</IfModule>
<IfModule mod_headers.c>
# disallow embedding of non https
Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
# Prevents browsers from interpreting text files as javascript
Header onsuccess unset X-Content-Type-Options
Header always set X-Content-Type-Options "nosniff"
# enable browser side cross site script filter
Header onsuccess unset X-XSS-Protection
Header always set X-XSS-Protection "1; mode=block"
# prevent search engines from indexing the site
Header onsuccess unset X-Robots-Tag
Header always set X-Robots-Tag "noindex, nofollow"
# prevent embedding in other sites
Header onsuccess unset X-Frame-Options
Header always set X-Frame-Options "SAMEORIGIN"
Header onsuccess unset X-Permitted-Cross-Domain-Policies
Header always set X-Permitted-Cross-Domain-Policies "none"
# prevent browser from sending referrer data when clicking links
Header onsuccess unset Referrer-Policy
# Header always set Referrer-Policy "no-referrer"
Header always set Referrer-Policy "same-origin"
</IfModule>
# Private, password protected directory
<Location "/private">
# authentication
AuthType basic
AuthName "My Server"
# Cache credentials with socache
AuthBasicProvider socache dbd
# also needed for caching: tell cache to cache dbd lookups
AuthnCacheProvideFor dbd
AuthDBDUserPWQuery "SELECT password FROM authn WHERE user = %s"
# block all non users.
Require valid-user
</Location>
<Location /nextcloud/>
Require all granted
AllowOverride All
Options FollowSymLinks MultiViews
<IfModule mod_dav.c>
Dav off
</IfModule>
# Disable Basic auth for this
Satisfy Any
</Location>
# SSL settings
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/host.tld/cert.pem
SSLCertificateChainFile /etc/letsencrypt/live/host.tld/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/host.tld/privkey.pem
#Include /etc/letsencrypt/options-ssl-apache.conf
# Add vhost name to log entries:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined
LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common
</VirtualHost>
</IfModule>
# vim: syntax=apache ts=4 sw=4 sts=4 sr et
我启用的模块:
access_compat.load authn_core.load authz_core.load autoindex.load dir.conf headers.load mpm_event.load proxy.load reqtimeout.conf security3.load socache_shmcb.load status.load
alias.conf authn_dbd.load authz_host.load dbd.load dir.load mime.conf negotiation.conf proxy_fcgi.load reqtimeout.load setenvif.conf ssl.conf unique_id.load
alias.load authn_file.load authz_user.load deflate.conf env.load mime.load negotiation.load proxy_http.load rewrite.load setenvif.load ssl.load xsendfile.load
auth_basic.load authn_socache.load autoindex.conf deflate.load filter.load mpm_event.conf proxy.conf proxy_wstunnel.load security3.conf socache_memcache.load status.conf
mpm_event.conf:
<IfModule mpm_event_module>
StartServers 2
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 150
MaxConnectionsPerChild 0
</IfModule>
apachectl-V:
Server built: 2024-07-17T18:57:26
Server's Module Magic Number: 20120211:126
Server loaded: APR 1.7.0, APR-UTIL 1.6.1
Compiled using: APR 1.7.0, APR-UTIL 1.6.1
Architecture: 64-bit
Server MPM: event
threaded: yes (fixed thread count)
forked: yes (variable process count)
Server compiled with....
-D APR_HAS_SENDFILE
-D APR_HAS_MMAP
-D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
-D APR_USE_PROC_PTHREAD_SERIALIZE
-D APR_USE_PTHREAD_SERIALIZE
-D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
-D APR_HAS_OTHER_CHILD
-D AP_HAVE_RELIABLE_PIPED_LOGS
-D DYNAMIC_MODULE_LIMIT=256
-D HTTPD_ROOT="/etc/apache2"
-D SUEXEC_BIN="/usr/lib/apache2/suexec"
-D DEFAULT_PIDLOG="/var/run/apache2.pid"
-D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
-D DEFAULT_ERRORLOG="logs/error_log"
-D AP_TYPES_CONFIG_FILE="mime.types"
-D SERVER_CONFIG_FILE="apache2.conf"
使用 curl 下载 2GB 静态文件时查看 /proc/meminfo。文本是在开始下载后大约 10 秒内 ssh 连接断开时显示的。到那时 curl 还没有收到一个字节。
MemTotal: 3880848 kB
MemFree: 190000 kB
MemAvailable: 479864 kB
Buffers: 52840 kB
Cached: 458780 kB
SwapCached: 63000 kB
Active: 502232 kB
Inactive: 2665432 kB
Active(anon): 318696 kB
Inactive(anon): 2479580 kB
Active(file): 183536 kB
Inactive(file): 185852 kB
Unevictable: 26756 kB
Mlocked: 26756 kB
SwapTotal: 4095996 kB
SwapFree: 2418916 kB
Dirty: 52 kB
Writeback: 192 kB
AnonPages: 2626292 kB
Mapped: 172496 kB
Shmem: 134752 kB
KReclaimable: 292096 kB
Slab: 411324 kB
SReclaimable: 292096 kB
SUnreclaim: 119228 kB
KernelStack: 8768 kB
PageTables: 22876 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 6036420 kB
Committed_AS: 8174592 kB
VmallocTotal: 133143592960 kB
VmallocUsed: 27632 kB
VmallocChunk: 0 kB
Percpu: 3216 kB
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
ShmemPmdMapped: 0 kB
FileHugePages: 0 kB
FilePmdMapped: 0 kB
CmaTotal: 65536 kB
CmaFree: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 0 kB