在 HAProxy 中设置后端某个站点的图片文件缓存时间为一年,主要通过 HTTP 响应头 来实现,HAProxy 本身不存储缓存内容,但可以在响应中添加 Cache-ControlExpires 头,指示客户端和中间缓存(浏览器、CDN)缓存图片一年。


方案一:基于文件扩展名匹配(推荐)

frontend web_frontend
    bind *:80
    bind *:443 ssl crt /path/to/cert.pem

    # 使用 ACL 匹配图片文件扩展名
    acl is_image path_end .jpg .jpeg .png .gif .webp .svg .bmp .ico

    # 为图片设置缓存头
    http-response set-header Cache-Control "public, max-age=31536000, immutable" if is_image
    http-response set-header Expires "%[date(),http_date(31536000)]" if is_image

    default_backend app_servers

backend app_servers
    server app1 192.168.1.10:80 check
    server app2 192.168.1.11:80 check

方案二:基于路径匹配(如 /static/images/ 目录)

frontend web_frontend
    bind *:80

    # 匹配特定路径下的图片
    acl is_image_path path_beg /static/images/ /uploads/avatars/
    acl is_image_ext path_end .jpg .jpeg .png .gif .webp

    # 组合条件
    http-response set-header Cache-Control "public, max-age=31536000, immutable" if is_image_path is_image_ext

    default_backend app_servers

方案三:为特定后端站点单独配置

如果需要对某个特定的后端站点(如 img.example.com)设置图片缓存:

# 图片专用前端
frontend img_frontend
    bind *:80
    bind *:443 ssl crt /path/to/cert.pem

    # 根据域名区分
    use_backend img_backend if { hdr(Host) -i img.example.com }

# 主前端
frontend web_frontend
    bind *:80
    default_backend app_backend

# 图片后端(缓存一年)
backend img_backend
    # 为所有响应设置缓存头(如果是纯图片服务)
    http-response set-header Cache-Control "public, max-age=31536000, immutable"
    http-response set-header Expires "%[date(),http_date(31536000)]"

    server img_server 192.168.1.20:80 check

# 普通应用后端
backend app_backend
    server app_server 192.168.1.10:80 check

方案四:条件判断避免覆盖已有缓存头

如果后端服务器可能已经设置了缓存头,可以使用 unless 避免覆盖:

backend app_backend
    # 仅当响应中没有 Cache-Control 时才设置
    http-response set-header Cache-Control "public, max-age=31536000, immutable" \
        if is_image { res.hdr(Cache-Control) -m found } !{ res.hdr(Cache-Control) -m found }

    # 或更简洁的方式:使用 set-header 但允许覆盖(通常没问题)
    http-response set-header Cache-Control "public, max-age=31536000, immutable" if is_image

    server app1 192.168.1.10:80 check

完整配置示例(生产推荐)

global
    log /dev/log local0
    maxconn 4096
    user haproxy
    group haproxy

defaults
    log global
    mode http
    option httplog
    option dontlognull
    retries 3
    timeout connect 5000
    timeout client 50000
    timeout server 50000

frontend web_frontend
    bind *:80
    bind *:443 ssl crt /etc/haproxy/certs/example.pem

    # ACL 定义
    acl is_image path_end .jpg .jpeg .png .gif .webp .svg .bmp .ico .tiff

    # 为图片设置一年缓存
    http-response set-header Cache-Control "public, max-age=31536000, immutable" if is_image
    http-response set-header Expires "%[date(),http_date(31536000)]" if is_image

    # 可选:设置 Vary 头,支持缓存压缩变体
    http-response set-header Vary "Accept-Encoding" if is_image

    default_backend app_servers

backend app_servers
    balance roundrobin
    option httpchk HEAD /health HTTP/1.1\r\nHost:\ example.com

    server app1 192.168.1.10:80 check inter 3000 rise 2 fall 3
    server app2 192.168.1.11:80 check inter 3000 rise 2 fall 3

关键配置说明

配置项 说明
max-age=31536000 缓存时长:365天(秒)
immutable 表示资源不会改变,浏览器可放心缓存(现代浏览器支持)
public 允许任何中间节点(CDN、代理)缓存
%[date(),http_date(31536000)] HAProxy 的 fetches,动态计算当前时间 + 31536000 秒后的日期
path_end ACL 匹配文件扩展名
set-header 设置响应头,如果已存在则覆盖

验证方法

配置生效后,通过 curl 验证:

curl -I http://your-domain.com/images/logo.png

预期响应头:

HTTP/1.1 200 OK
Cache-Control: public, max-age=31536000, immutable
Expires: Thu, 27 Mar 2025 10:00:00 GMT
Content-Type: image/png

注意事项

  1. HAProxy 不缓存实际内容:只添加响应头,真正的缓存由浏览器/CDN 完成
  2. 动态图片谨慎处理:如果图片内容会变化,不应设置过长缓存
  3. 与后端协调:如果后端(如 Nginx)已设置缓存头,HAProxy 的 set-header 会覆盖
  4. SSL 配置:如果使用 HTTPS,确保证书路径正确
  5. Expires 动态计算:使用 %[date(),http_date(31536000)] 需要 HAProxy 2.2+ 版本

如果你需要针对特定后端服务器(而非域名或路径)进行缓存配置,或者需要配合 CDN 设置 s-maxage,我可以进一步补充。

文档更新时间: 2026-03-27 07:28   作者:月影鹏鹏
IT运维支持-AIWALY-月影工作室