Skip to main content

概述

kira-imgproxy 是基于 imgproxy 的图片处理服务,提供动态图片缩放、格式转换、模糊等功能。

部署信息

配置
平台Fly.io
域名img.kira.art
区域sjc (San Jose)
内存8GB
CPU8 vCPU (shared)
端口8080

URL 签名

imgproxy 使用 HMAC-SHA256 签名保护 URL,防止滥用。

签名算法

import crypto from "crypto";

function signImgproxyPath(path: string): string {
  const key = Buffer.from(IMGPROXY_KEY, "hex");
  const salt = Buffer.from(IMGPROXY_SALT, "hex");

  const hmac = crypto.createHmac("sha256", key);
  hmac.update(salt);
  hmac.update(path);

  return hmac.digest("base64url");
}

URL 格式

https://img.kira.art/{signature}/{processing}/{source}@{format}
示例:
https://img.kira.art/CQTBc5cY.../rs:fit:400:0/plain/https%3A%2F%2F...@webp

处理参数

缩放 (resize)

rs:{type}:{width}:{height}
参数说明
rs:fit:400:0宽度 400px,高度自适应
rs:fill:200:200填充到 200x200
rs:auto:800:600自动选择最佳方式

模糊 (blur)

bl:{sigma}
示例:bl:5 - 高斯模糊,sigma=5

质量 (quality)

q:{quality}
示例:q:80 - 压缩质量 80%

环境变量

性能配置

IMGPROXY_WORKERS = "8"               # 工作线程数 (CPU × 1)
IMGPROXY_TIMEOUT = "120"             # 处理超时 120 秒
IMGPROXY_DOWNLOAD_TIMEOUT = "120"    # 下载超时 120 秒
IMGPROXY_TTL = "2592000"             # Cache-Control max-age (30 天)

安全限制

IMGPROXY_ALLOWED_SOURCES = "*"
IMGPROXY_MAX_SRC_RESOLUTION = "50"        # 最大 50MP
IMGPROXY_MAX_SRC_FILE_SIZE = "52428800"   # 最大 50MB
IMGPROXY_MAX_ANIMATION_FRAMES = "100"     # 最大动画帧数

图片质量

IMGPROXY_QUALITY = "80"
IMGPROXY_FORMAT_QUALITY = "avif=65,webp=75,jpeg=80"
IMGPROXY_STRIP_METADATA = "true"          # 移除 EXIF 等元数据
IMGPROXY_AUTO_ROTATE = "true"             # 自动修正方向

格式检测

IMGPROXY_AUTO_WEBP = "true"
IMGPROXY_AUTO_AVIF = "true"
IMGPROXY_PREFERRED_FORMATS = "avif,webp,jpeg"

内存管理

IMGPROXY_MALLOC = "jemalloc"                              # 内存分配器 (防止 OOM)
IMGPROXY_FREE_MEMORY_INTERVAL = "10"                      # 每 10 秒强制释放内存
IMGPROXY_DOWNLOAD_BUFFER_SIZE = "41943040"                 # 下载缓冲区 40MB
IMGPROXY_BUFFER_POOL_CALIBRATION_THRESHOLD = "256"
GOMEMLIMIT = "6GiB"                                       # Go 运行时内存限制

请求与 CORS

IMGPROXY_REQUESTS_QUEUE_SIZE = "64"
IMGPROXY_ALLOW_ORIGIN = "*"
IMGPROXY_USER_AGENT = "Mozilla/5.0 (compatible; KiraImgProxy/1.0; +https://kira.art)"

Fallback 图片

IMGPROXY_FALLBACK_IMAGE_URL = "https://base.kira.art/storage/v1/object/public/public_material/place_holder/image_error.png"
IMGPROXY_FALLBACK_IMAGE_HTTP_CODE = "200"

健康检查

fly.toml 中配置:
[[http_service.checks]]
  grace_period = "5s"
  interval = "30s"
  method = "GET"
  path = "/health"
  timeout = "5s"

自动停止

fly.toml 中配置:
auto_stop_machines = 'stop'
auto_start_machines = true
min_machines_running = 0

密钥配置

签名密钥存储在 Fly.io secrets 中:
fly secrets set IMGPROXY_KEY=<hex-key> IMGPROXY_SALT=<hex-salt>
密钥必须是 hex 编码的字符串,至少 32 字节。

缓存策略

响应头

imgproxy 返回的 Cache-Control 头:
Cache-Control: public, max-age=2592000

Cloudflare CDN

在 Cloudflare Dashboard 为 img.kira.art 配置 Cache Rules:
  1. Cache eligibility: Eligible for cache
  2. Edge TTL: Use origin Cache-Control header
  3. Browser TTL: Use origin Cache-Control header

开发

本地运行

cd kira-imgproxy

# 使用 Docker
docker run -p 8080:8080 \
  -e IMGPROXY_KEY=your_key \
  -e IMGPROXY_SALT=your_salt \
  ghcr.io/imgproxy/imgproxy:latest

部署

fly deploy

监控

OpenTelemetry

imgproxy 集成了 OpenTelemetry,将指标发送到 BetterStack:
IMGPROXY_OPEN_TELEMETRY_ENABLE = "true"
IMGPROXY_OPEN_TELEMETRY_ENABLE_METRICS = "true"
OTEL_EXPORTER_OTLP_PROTOCOL = "http/protobuf"
OTEL_SERVICE_NAME = "kira-imgproxy"

可用指标

指标说明
workers_utilizationWorker 利用率 (0-1)
vips_memory_byteslibvips 内存使用量
images_in_progress正在处理的图片数
goroutinesGo 协程数量
heap_mbGo Heap 内存
process_mb进程总内存

建议报警阈值

指标WarningCritical
Worker Utilization> 50%> 80%
Process Memory> 6GB> 7GB
Images In Progress> 100> 150
Goroutines> 50> 100

Fly.io 监控

通过 Fly.io 监控面板查看:
  • 请求量
  • 响应时间
  • 内存/CPU 使用
  • 错误率

文件结构

kira-imgproxy/
├── .github/
│   └── workflows/     # CI/CD
├── Dockerfile         # 基于 imgproxy 官方镜像
└── fly.toml           # Fly.io 配置