Golangで画像プロキシサーバをつくった
Graidという画像プロキシサーバをつくりました。
外のサーバから画像を取得してリサイズしたりして返す、ということをするサーバです。
Golangでなんかミドルウェア的なものが作ってみたかったのでやってみました。
Graidについてのスライド
エンジニアが集まってお昼ご飯を食べながら技術的なネタを話すテックランチという会が社内で定期的に開催されているので、Graidについて話してきました。
機能
http://localhost:8080/path/to/image.jpg:w400:h300:q80
例えば8080ポートで起動させてURLにアクセスすると、
- オリジンの画像サーバ(設定ファイルに設定する)の/path/to/image.jpgを取ってきて
- 横400px、縦300pxにリサイズして画質80%に加工して
- レスポンスを返す
という処理をします。:w400:h300:q80
の部分が画像加工のクエリ、その中の:w
とか:h
が処理内容を決定するオペレータです。つなげて複数することができます。
オペレータ
リサイズの他に、今のところ以下のオペレータがあります。
オペレータ | 説明 | 例 |
---|---|---|
:w | 画像の横幅を指定してリサイズ。(:hを指定しない場合は横幅に合わせてリサイズ) | :w400 |
:h | 画像の縦幅を指定してリサイズ。(:wを指定しない場合は縦幅に合わせてリサイズ) | :h300 |
:q | jpegの品質(1〜100) | :q80 |
:c | クロップ。2点の座標をカンマ区切りで指定する。 | :c40,10,220,240 |
:grayscale | 白黒フィルター。 | :grayscale1 |
:sepia | セピアフィルター。(1〜100) | :sepia100 |
:contrast | コントラストの調整。 | :contrast50 |
:brightness | 明るさの調整。 | :brightness-50 |
:saturation | 彩度の調整。 | :saturation80 |
:colorize | カラーフィルター。 | :colorize240,50,100 |
:colorbalance | カラーバランスフィルター。 | :colorbalance20,-20,0 |
画像処理
いまのところjpegだけ対応しています。
画像処理部分はgiftに渡す仕組みになっています。簡単に加工ができて便利です。 最初はリサイズとクロップができればいいなぐらいに考えていたのですが、giftがとても便利なので他のオペレータもつくってみました。
フィルターを組み合わせてインスタグラムみたいなオペレータがつくれそうですね。
ImageMagickのラッパーであるgographics/imagickを使うかImageMagickのconvertをキックするか、迷ってライブラリを探していたのですが、 fawick/speedtest-resizeをみてgiftを知りました。各ライブラリで計測した画像リサイズ速度が載っています。
キャッシュ
外部から取得して加工した画像はクエリごとにキャッシュして、次のアクセスから速くレスポンスを返します。キャッシュの保存先はファイルかRedisです。設定ファイルで指定することができます。
また、クエリのURLに?nocache=1
をつけるとキャッシュを無視してもう一度リモートから画像を取得します。
設定ファイル
graid/graid.toml at master · violetyk/graid · GitHubが設定ファイルです。起動するポート、ワーカープールサイズ、キャッシュ、オリジンサーバの指定などを設定します。
TOMLで記述します。TOMLはGolang製静的サイトジェネレータのHugoで使われています。階層構造や配列がかけるiniファイルのようなフォーマットで、よさげです。各種言語で実装されたパーサやエディタのシンタックスハイライトもそろっています。
今後
daemonといいつつまだデーモンとして実装できていないのでなのとかしたいです。
あとは、
- jpeg以外の画像フォーマットへ対応
- オペレータの指定をコロンではなくてGETパラメータにするモードの作成
- タイムアウトの指定ができるように
- HTTPクライアントの同一ホストへの最大コネクション数の指定
- 各処理のベンチマークする仕組み
を実装しようかと思っています。