出、出、出〜ameba画像配信奴〜!! | サイバーエージェント 公式エンジニアブログ
はじめまして。インフラ所属の@saeoshiと申します。仕事中にAAを作成して
skypeに貼付けるという作業を主にやっています。社内の一部からは職人と呼ばれています。

あとはロックのかかっていないPCを見つけては、壁紙とskypeの画像を変更する作業も
かかさず行い、社内セキュリティにも貢献しています。アッーーーー!!

席も窓際なので、そろそろクビになるのでしょうか。
@oranie同様、僕もダーツかなんかで決められたのでしょう。


さてさて、そんな駄目エンジニアが書くネタとして
「エンジニア流 親への結婚挨拶」「エンジニア流 酒の飲み方」「インフラエンジニア 3K」なんて書こうかと思いましたが、本当にクビにされそうなので、やめておきましょう。

僕は画像基盤の構築・運用をメインにやっているので今回はAmebaの画像基盤に関してご紹介させていただきます

モヒカン様たち、種籾は奪わないでください

旧構成
以下の図が旧構成の概要図です。


参照時の受け口はメインがakamaiになっています。トラフィック的にはピーク時で15G近くさばいてます。
そこから、ガラケー向けWebApplicationサーバ(ガラケーリサイズ用:以下mobile-wap)、スマートフォン向けWebApplicationサーバ(SP、PCのリサイズ用:以下spwap)、original(オリジナル画像配信用)に
WebApplicationサーバ(以下wap)を分けた構成になっています。
それぞれ、cacheをもっていてmobile-wap=memcached、spwap=kyototycoon、wap=squidになっています。

それぞれのcacheを分けている理由は様々あります。
例えば、HTTPとの親和性が高いsquid、ガラケーの変換画像の高速化のためのmemcached、memcacheのプロトコルがしゃべれて永続化もできるkyototyconnなど。その当時のやりたいこと、事情にあわせて導入されています。

originalのstorageに関しては、サーバ<=>エンクロージャ型のDAS構成を取っています。
HDDはHGST 2TBを使用しています。

mobile-wapだけuser-agentを判定しての画像処理もおこなっているので
akamaiは経由しない形になっています。
※最近、akamaiでuser-agentを判定した処理が出来るようになったとか・・・?

ポイント
旧構成のポイントです。

cacheの部分に関しては、wapであるnginxのupstream_hash moduleと、healthcheck moduleを使ってURLをkeyにhash化し、cachehが重複しないよう、ノードがdownしたら切り離すようになっています。

sp、mobileに関してもconsistent hashを使った構成になっていてcacheが重複しないようになっています。

originのcacheの設定はこんな感じです


upstream upstreams_cache
{
server xxx.xxx.xxx.xxx:xxxx;
server xxx.xxx.xxx.xxx:xxxx;

hash $filename;
hash_again 10;
healthcheck_enabled;
healthcheck_delay 3000000;
healthcheck_timeout 7000;
healthcheck_failcount 2;
healthcheck_send "GET /xxxxx/xxxxx.jpg HTTP/1.0" 'Host: stat001.ameba.jp' 'Connection: close';
}


DASの部分に関してはHDD、RAIDカードともにチューニングをおこなっており安上がりな構成ながら、パフォーマンスと11TBの大容量を兼ね備えた構成になってます。

下記チューニングの一例ですが、
I/0スケジューラをdeadlineに設定しています。


title CentOS (2.6.18-164.el5)
        root (hd0,0)
        kernel /vmlinuz-2.6.18-164.el5 ro root=LABEL=/ elevator=deadline
        initrd /initrd-2.6.18-164.el5.img



また、RAIDカードのパラメータはWritback、bs/512K、マウントパラメータはnoatime,nobarrier、queue_depthなども設定しています。

リニューアル構成
現在、上記の構成をリプレースしており
次期には分散ファイルシステムのOpenstack Swiftを使用した構成になります。
Swiftに関しては最近話題なので、ここでは割愛します。


ちなみにSwiftを採用した理由としては、こんな感じです。

・分散できる(*´ω`*)
・RESTful(*´ω`*)
・pythonでかかれてる(*´ω`*)
・自動復旧機能がある(*´ω`*)
・コミュニティが活発(*´ω`*)
・試験的にもよかった(*´ω`*)


まず分散できるという点。
Swiftはデフォルトで3つのレプリカを持つことができます。
また、zoneという概念をもっており、同じオブジェクトは複数のzoneに別れる=つまり同じzoneには格納されないということになります。

例えば、zone1に所属するサーバAがおちてもzone2とzone3にレプリカがあるので参照は可能になりますね。

swiftにはおおまかに下記のコンポーネントがあります。
・proxy(リクエストの中継、各ノードへの分散、認証)
・account(accountが保持しているcontainerのリストを扱います)
・container(s3でいうbucketですね。objectのリストを扱います)
・object(実データです)

それぞれの機能に関してもzoneごとに分割、レプリカを持つことが出来るのでSPOFがありません。

・restfulなのでGETもHEADもHTTPサーバと同じ要領でできます。
・Putでファイルアップロードもできます。例としてはこんな感じ、


まず、proxy(auth)からtokenを取得します

※認証はswauthを使用しています。

# swift -A http://xxx.xxx.xxx.xxx:8080/auth/v1.0 -U test:tester -K testing stat -v

StorageURL: http://xxx.xxx.xxx.xxx:8080/v1/AUTH_1b51f596-eb3f-48a6-9d7f-e9140f558dfe
Auth Token: AUTH_tka8a3ffaa80da43f7bb043b44a614219f
   Account: AUTH_1b51f596-eb3f-48a6-9d7f-e9140f558dfe
Containers: 1
   Objects: 2
     Bytes: 371525
Accept-Ranges: bytes
X-Timestamp: 1358753108.30532
X-Trans-Id: tx901b4159276242cba3295d68e82b5d22
Content-Type: text/plain; charset=utf-8



取得したtokenを使ってファイルをputします。


curl -v -T test.jpg -X PUT -H 'X-Storage-Token: AUTH_tk39d550c870d94a25aa2b93862273f487' http://xxx.xxx.xxx.xxx:8080/v1/AUTH_1b51f596-eb3f-48a6-9d7f-e9140f558dfe/udagawa/test.jpg
* About to connect() to xxx.xxx.xxx.xxx port 8080 (#0)
*   Trying xxx.xxx.xxx.xxx... connected
* Connected to xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx) port 8080 (#0)
> PUT /v1/AUTH_1b51f596-eb3f-48a6-9d7f-e9140f558dfe/udagawa/test.jpg HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15
> Host: xxx.xxx.xxx.xxx:8080
> Accept: */*
> X-Storage-Token: AUTH_tk39d550c870d94a25aa2b93862273f487
> Content-Length: 41165
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
< HTTP/1.1 201 Created
< Content-Length: 118
< Content-Type: text/html; charset=UTF-8
< Etag: 1d67eda4cb9b4ee81b57a8f741b3bf9b
< Last-Modified: Thu, 15 Nov 2012 08:07:23 GMT
< Date: Thu, 15 Nov 2012 08:07:23 GMT
<
<html>
 <head>
  <title>201 Created</title>
 </head>
 <body>
  <h1>201 Created</h1>
  <br /><br />
 
 
 </body>
* Connection #0 to host xxx.xxx.xxx.xxx left intact
* Closing connection #0



自動復旧機能に関しては、例えばobjectの場合Auditorプロセスとreplicatorプロセスが
データの状態をチェックし、異なる場合に自動で複製、置き換えをしてくれるというすぐれものです。

壊れたnodeを外して、再度別nodeを組み込んであげればできますが
例えばobjectを間違って削除してしまった場合、こんな感じで復旧してくれます。

ざっくばらんに。

※objectの親ディレクトリにあるhashes.pklも必ず消すこと。消さないと、replicatorが削除されたことを感知できないのでー。


root@swift-con01:/srv/node/sdb1/objects/222204# ls -l
total 4
drwxr-xr-x 3 saeoshi saeoshi  45 Dec 26 14:15 159
drwxr-xr-x 3 saeoshi saeoshi  45 Dec 26 14:15 2bb
drwxr-xr-x 3 saeoshi saeoshi  45 Dec 26 14:15 a82
drwxr-xr-x 3 saeoshi saeoshi  45 Dec 26 14:15 b24
drwxr-xr-x 3 saeoshi saeoshi  45 Dec 26 14:15 e20
-rw------- 1 saeoshi saeoshi 223 Dec 26 14:15 hashes.pkl
root@swift-con01:/srv/node/sdb1/objects/222204#
root@swift-con01:/srv/node/sdb1/objects/222204# ls -l e20/d8ff1b40757392c4af291b9839ae1e20/1356405624.80957.data
-rw------- 1 saeoshi saeoshi 211481 Dec 26 14:15 e20/d8ff1b40757392c4af291b9839ae1e20/1356405624.80957.data
root@swift-con01:/srv/node/sdb1/objects/222204#
 
#
#objectをrmする
#
 
root@swift-con01:/srv/node/sdb1/objects/222204#
root@swift-con01:/srv/node/sdb1/objects/222204# rm -fR e20/ hashes.pkl
root@swift-con01:/srv/node/sdb1/objects/222204# ls -ltr
total 0
drwxr-xr-x 3 saeoshi saeoshi 45 Dec 26 14:15 b24
drwxr-xr-x 3 saeoshi saeoshi 45 Dec 26 14:15 a82
drwxr-xr-x 3 saeoshi saeoshi 45 Dec 26 14:15 2bb
drwxr-xr-x 3 saeoshi saeoshi 45 Dec 26 14:15 159
 
#
#確認する
#
 
root@swift-con01:/srv/node/sdb1/objects/222204# ls -ltr
total 4
drwxr-xr-x 3 saeoshi saeoshi  45 Dec 26 14:15 b24
drwxr-xr-x 3 saeoshi saeoshi  45 Dec 26 14:15 a82
drwxr-xr-x 3 saeoshi saeoshi  45 Dec 26 14:15 2bb
drwxr-xr-x 3 saeoshi saeoshi  45 Dec 26 14:15 159
drwxr-xr-x 3 saeoshi saeoshi  45 Dec 26 14:42 e20
-rw------- 1 saeoshi saeoshi 223 Dec 26 14:42 hashes.pkl
root@swift-con01:/srv/node/sdb1/objects/222204# ls -l e20/d8ff1b40757392c4af291b9839ae1e20/
total 208
-rw------- 1 saeoshi saeoshi 211481 Dec 26 14:42 1356405624.80957.data


簡単ですねー。

swiftに関しては、他にも様々な機能(objectのexpire、versioningとかCORSとか)とかいろいろ
あるのでcommunityやらを見ておくとよいですね。

http://docs.openstack.org/developer/swift/

まだ完全にできていないので、ここではあまり書けませんが、そのうちまたどっかで情報出したいと思います。

ざっくばらんに書いてしまいましたが、こんな感じでおゆるしください。
ではノシシ