Golang / 运维相关 · 2022年8月15日 0

使用imgproxy来构建你的图片边缘计算服务

很多云服务商都提供图片静态资源的在线调整尺寸的服务,对于个人小应用来说,使用这些厂商的服务很麻烦,而且还需要额外的开销。比如我希望白嫖CloudFlare的cdn,那就得另想办法。而ImgProxy就是目前我能找到的最好的解决方案,它可以原始图片进行压缩,裁剪,旋转,模糊等一系列操作,进而减少流量。比如原图可能是8K大小的图,大概15M左右,当我需要图像列表的时候,实时处理成320×240大小的图,也就几K大小,这样一来,网页打开的速度也大大加快。

根据官方给出的架构图,可以大致确定一个运行方式,即:

  1. 需要一个源图地址的CDN域名
  2. 需要一个imgproxy的CDN域名

同时官方也给出了一个市面上类似应用的对比图,由于imgproxy是go写的,所以无论是内存占用还是性能上,表现都很出色,同时使用简单,非常适用于一些个人项目,或者不太大的商业项目。

前面说了,需要两个CDN域名,之所以源图资源需要CDN,因为imgproxy最终的url其实就是一堆base64编码的东西,解码出来其实就是源图地址,如果源图不加CDN的话,可能就被干爆了。

用docker来搭一个imgproxy也很简单,下面是docker-compose的例子

version: "3.3"

services:

  imgproxy:
    image: darthsim/imgproxy
    container_name: imgproxy
    restart: always
    networks:
      - work-net
    environment:
      # 读取源文件超时秒数
      - IMGPROXY_READ_TIMEOUT=30
      # 可以处理的原图最大分辨率,百万,举例:8K分辨率为7680 × 4320 约3300万,对应处理的值就是33
      - IMGPROXY_MAX_SRC_RESOLUTION=100
      # 发送给浏览器的图片缓存秒数,180天
      - IMGPROXY_TTL=15552000
      # 日志级别
      - IMGPROXY_LOG_LEVEL=error
      # 加密用的KEY/SALT
      - IMGPROXY_KEY=a14cd90aad80d
      - IMGPROXY_SALT=404a64f2e43ee
    labels:
      # imgproxy
      - "traefik.enable=true"
      - "traefik.http.routers.imgproxy.rule=Host(`imgproxy.anerg.com`)"
      - "traefik.http.routers.imgproxy.entrypoints=websecure"
      - "traefik.http.services.imgproxy.loadbalancer.server.port=8080"
      - "traefik.http.routers.imgproxy.service=imgproxy"
      - "traefik.http.routers.imgproxy.tls=true"
      - "traefik.http.routers.imgproxy.tls.certresolver=cloudflare"

networks:
  work-net:
    external: true

我只配置了我认为比较重要的参数。因为我不想这个服务被白嫖,那么就要加上加密,例子中相关参数已经有解释了,关于KEY和SALT,根据官方文档,可以用以下命令生成。

echo $(xxd -g 2 -l 64 -p /dev/random | tr -d '\n')

最终生成的url地址大概会是这样的

https://imgproxy.anerg.com/eE5pJp-yowc/w:300/h:400/q:100/aHR0cHM6Ly9tLm1l.jpg

其中eE5pJp-yow这一段就是加密,w:300/h:400/q:100是对图片的操作,aHR0cHM6Ly9tLm1l是图片实际的url地址的base64编码。

具体的可以参考官方文档的说明:https://docs.imgproxy.net/

同时我也写了一个golang的操作库,https://github.com/anerg2046/imgproxy-go

除了付费pro版的操作,其他方法基本都支持了,用法也很简单

package main

import (
	"fmt"

	imgproxygo "github.com/anerg2046/imgproxy-go"
)

func main() {
	imgproxy := imgproxygo.N(imgproxygo.Config{
		BaseUrl:       "http://localhost:8080",
		Key:           "736563726574",
		Salt:          "68656C6C6F",
		SignatureSize: 8,
		Encode:        true,
	})
	s := imgproxy.Builder().Width(300).Height(400).Quality(100).Gen("https://m.media-amazon.com/images/M/MV5BMmQ3ZmY4NzYtY2VmYi00ZDRmLTgyODAtZWYzZjhlNzk1NzU2XkEyXkFqcGdeQXVyNTc3MjUzNTI@.jpg")
	fmt.Println(s)
}

总结

对于白嫖党来说,这个东西基本是个vps都能跑的起来,性能高,占用小,是个很不错的东西,但是需要一点动手能力才能折腾。