2015-07-06: #kosendj #kosenvj を支える技術 (バックエンド編)

2015-06-27 16.42.40

#kosenvj を支える技術(フロント編) のバックエンド編です。 高専DJ部 (kosendj-bu) 御用達の「GJ」とよばれる VJ もどきシステムのバックエンドについて説明したい。

GJ? VJ?

詳細は ↑ の @neo6120 が書いたエントリを見てほしいのだけど、簡単に言うとインターネットにありふれた gif を適当につかって VJ をしようみたいな試み。 ↓ の動画をみるとなんとなくわかるかも。

やばいかんじある #kosendj

A video posted by yuya fujiwara (@asonas) on

現場の様子です #kosendj

A video posted by yuya fujiwara (@asonas) on

kosendj-bu #3 まで

まずは今迄どうやっていたかの話をする。 gj については ↑ に貼った @neo6120 のエントリを読んでもらうとして、こんなかんじ。

フロントしかなくてバックエンドとかはなかった。GJ のフロントエンドアプリは Heroku 上にホストされてるし、裏側で人間が頑張って GIF を集めて流すという感じ。会場の Wi-Fi が貧弱なのとそもそもの上流回線が細いというのがあって GIF の取得が間に合わずブラックアウトしまくる、という悲惨な状態だった。

で、↑ のように急遽自分のマシンに gif 配信するための nginx とかたてたけどそれも Wi-Fi にのってて結局きびしい、みたいな感じになってつらかった。

あとは GIF の整理自体も自分が適当にローカルにおいてあるのを全部上げておいてファイル探すのだけ OS X の Finder つかって URL 生成して投げるみたいな感じでギリギリなんとかなるレベルだった。

改善するぞ

個人的には gif jockey 最高だけどこれはめっちゃ問題だわと思っててこのへんは次改善しなきゃなーという感じで終わった。というわけで GJ のための GIF の配信まわり、安定したインターネット、GJ のための GIF 整理・管理とかをどうにかしようと思った。

しかし kosendj-bu #4 は ミリオンライブの 2nd ともろ被りしてていけなかったので #5 で改善を投入した。

しかし deadline は決まってるのに直前一週間になって自分の DJ もあるのに準備しはじめるあたりはアホだと思った。

gjcase

https://github.com/kosendj/gjcase

まず gif の整理問題を解決するためにつくった。 Rails + garage + React.js みたいな構成になっている Web app。

とりあえずタグ付けと検索、および GJ への送信、適当に tumblr から引っ張ってくる、ミラーリングくらいの機能しかない。GIF 追加すると sidekiq で非同期でよきに S3 へミラーしてくれたりする。

↑タグの追加

↑タグ検索

急ピッチ (作業時間 18 時間くらい、ほとんど開催前日深夜) で作ったのでいろいろ雑。次回までにもうちょっと UI マシにしたりいろいろしたい。一応、これだけでも VJ 業はこなせるという事はわかっている。

あ、開発してて Promise とか ES6 classes 便利だな〜とおもった。べんり。 models/base.js.jsx とかは garage のクライアントとして便利につかえるようにちょっと頑張って書いた。タグを追加するなら Image.get('42').then((data) => data._links.image_tags.post('72') ) みたいな感じで書ける。

インフラ面

会場のインターネットの安定さがよくわからない、すくなくとも Wi-Fi は不安定になるし GIF をめっちゃ見てたりするとすごい不安定になる、という感じだったのでとにかくインターネットと GIF の配信を快適にするというのが目的。今回の会場 (茶箱さん) の方で有線で一本つながせてほしいとお願いして、有線でのインターネット接続を得たからその先の面倒を見る。 (協力助かりました!)

で、実際に kosendj-bu #5 で投入した構成は物理的にはラップトップ x 2, スイッチ x 1, Wi-Fi AP x 1 といったところ。手持ちの機材の関係でこうなったんだけど次回はラップトップ x 1 にしたい。

なお、インフラ周りはだいたい codification されてて https://github.com/kosendj/ops でいろいろ公開してます。itamae のファイルとか参考にどうぞ。

構成

左は物理、右は論理な構成図。雑だけど。

Thinkpad X60 (hostname: retoree) が storage, router, camo をしていて、MacBook Air 11" (hostname: cyan) が gjcase, gj の app サーバーをやっている。ホスト名はたまたま最近 SHOW BY ROCK!! めっちゃいいってなってたからプラズマジカからつけた。後悔ハシテイナイ

ディストリビューションは全部 Ubuntu 15.04 Vivid で provisioning は全部 itamae で済ませた。Arch, Gentoo はちょっと時間がなかったし自分以外も触る事を考えて自重した。

ネットワーク

一応 GS105Ev2 で 802.1q VLAN を切ってた。Wi-Fi 含むクライアントを収容するのと、サーバーと、会場側回線と、マネジメントで 4 VLAN を切った。といっても server にいるのは cyan だけだし、management は retoree だけだし、趣味って感じだ。会場側のドメインは box.ops.kosendj-bu.in にした。

retoree が dnsmasq を持ってて DNS/DHCP と、あとは IPv4 forwarding を有効にしてルーティング・NAT を担当していた。dnsmasq は一部 FQDN を会場内のネットワークに向けるような設定が入ってる。

GIF のストレージ

前回は会場のインターネット帯域を使い切ったというのもあって今回の最大の目的はインターネットにトラフィックを極力流さないって感じだった。当然 GIF のトラフィックは会場内で完結させる必要がある。

前述の通り gjcase で事前にある程度 gif を集めておいた。gjcase にある分は S3 に全部ミラーされてるので、家であらかじめ aws s3 sync しておいて、それを retoree から nginx で配るようにした。(これを storage と呼称します)

gj は基本 gj で持っているプロキシみたいなエンドポイントをブラウザから GIF の読み込みに利用しようとするが、これは x-gif のために CORS ヘッダをつけて返すため。直接 CORS ヘッダを返せばこれは省けるので、一部 URL は直接読みにいくような雑なコミットを gj に入れて、storage (nginx) 側で CORS 周りのヘッダを返しつつ、直接ブラウザからリクエストを受けるようにしている。

開催中も開催中じゃないときもおなじ URL でそのまま外のネットワークで見えるとうれしい。なので外のネットワークでも同じストレージの URL で使える、ただし外では直接 Cloudfront が捌くように、みたいな事もできるようにしているけど外にはそもそもまだ gj, gjcase を置いてない。

開催中の GIF 追加への対応

開催中も GIF を追加することは予想されるので、以下のような対策を打った。実際何度かドカッと追加したりしてた。

  • 追加された GIF の S3 へのミラー
    • gjcase は sidekiq で非同期にミラーリングを走らせるようにしている。
    • sidekiq は AWS 側におくようにした。本来まあミラーは開催中にされたやつはしなくてもいいか、と思ったけど思ったより追加したので EC2 に redis, mysql を ssh port forwarding して EC2 で sidekiq を走らせていた。
  • S3 へのミラーが終わってない画像用に camo の設置
    • gj は x-gif を利用していて、XHR2 によるクロスドメイン通信 が GIF に対して許可されていないといけない
    • gj のプロセスでいままではプロキシしていたけど、今回はプロセスとかサーバーを分けられるように camo を使うことにした。
    • URL の生成は gjcase 側でやってる。gjcase が提示してくる URL はミラーリングがされている (パスの情報が DB に入ってる) なら storage の URL を出してきて、そうじゃないなら camo を通した URL を出すようになっている。
    • camo の手前に nginx を置いて proxy_cache させる事で 2 度目以降のロードは帯域食わないようにとか。
  • S3 のミラーがされているが retoree, cyan ともにローカルに画像がない場合に備える
    • nginx で普通に try_files でファイルがなかったら Cloudfront にリバースプロキシするようにした。ここでも当然 proxy_cache している
    • 後々、人間の手で会場内から aws s3 sync も叩いてた。

その他

  • gif 結構重くて、複数人で gif 眺めてたりすると普通に 100Mbps 使い切る。うける。
  • http2 やってもいいかなと思ったけど SSL 証明書間に合いませんでした。
  • ssh tunnel じゃなくて OpenVPN とかで済ませようとおもったけどちょっと間に合わなかった。サーバーつくりはじめたの当日の朝だしな…
  • retoree (X60) は iowait がひどかったので storage は開催中に cyan に役割を譲った。
    • 本来 MBA だけでいいんだけど、持っていった MBA は Late 2010 で USB 2.0 のみ、つまり 100Mbps Ethernet が限界なので X60 も持っていったのでした…。100Mbps 使い切ってたけど iowait よりマシ、ってかんじ

VJ 業

アニメやゲームぽかったら頑張ってイントロドンを脳内でやってシュッと gjcase から GIF を出したり。普通のクラブミュージックなら適当に gjcase 漁りながら気分で画像を投げていく。というだけ。

わたしは iTunes Store の Anime ジャンルは毎週漁っては購入しているので曲は大量にきいてるし持ってるけど、作品がパッと分からない事が多いのでつらい。精進が必要。

(事前に教えてくれ!!! とは言ってるけど知りきれないのが現状なんだよな)

まとめ

高専 DJ 部における VJ をどう運用しているかの話でした。実際たいした事はしてないと思っている。
次回以降は他の人も乱入しやすい状態にしやすいなあと思ってます。ちょっと今回は準備が急ピッチすぎていろいろ気が回らなかったきがしている…。

次回もやると思うので、よろしくね。

Published at 2015-07-06 08:11:29 +0900