Quantcast
Channel: サイバーエージェント 公式エンジニアブログ
Viewing all 161 articles
Browse latest View live

Android Meetup

$
0
0

こんにちは。
私はサイバーエージェントでディベロッパーをしております、Patrick Boosです。

この度弊社セミナールームにて、外国人コミュニティーでのAndroidミートアップを開催致しました。
一年半前に行った前回のミートアップにおける参加者は10名程度でしたが、今回はその約二倍の19名にご参加いただきました。このようなミートアップに興味を持つ方が増えているということでしょう。今後はもっと定期的に開催していきたいと思います。

サイバーエージェント 公式エンジニアブログ-People サイバーエージェント 公式エンジニアブログ-Presentation


こちらのミートアップはGoogle IOの翌週に開催致しましたので、Google IOでのアナウンスメントについても議題にあがりました。その他は、それぞれが今関わっているプロジェクトについてプレゼンをしたりアンドロイドでの検証についてディスカッションを行いました。
私たちは、またこのような、知識をシェアしたりネットワークを広げることができ、それぞれが刺激しあい高められるような会を開きたいと思っております。

来月開催予定の次回ミートアップも楽しみにしております。

また、この会には日本人エンジニアも参加しており、英語で会話をしましたが、非常に大変そうに感じました。でもそれは彼がシャイなだけであって、話せないわけではないと思いました。ナーバスになっていただけだと思います。日本人にもっと外人の前で英語で自身を表現する機会を用意できたらと思います。


キラキラ女子を支える技術

$
0
0

こんにちは!12新卒エンジニアの白木みつか(@32ka)です。
堂本剛をこよなく愛する23歳独身です。


最近「キラキラ女子」なるもの日経の記事にとりあげられ話題になりました。

サイバーエージェント、躍進支える「キラキラ女子」サイバー流、女性活用の研究(1)
「キラキラ女子」集結の謎、藤田晋社長が戦略語るサイバー流、女性活用の研究(2)
「キラキラ女子」を引き寄せる会社の条件 憧れ、説得力、多様性…サイバー流、女性活用の研究(3)

うちの女性社員はよくまとめにあがってきたりして、社外ではものすごい華やかなイメージを持たれています。
そんな中にいる、エンジニアについてはなかなか取り上げられません。。。
エンジニアだって頑張ってるんです!キラキラ女子だけじゃないんです!と思っているわけであります。

とゆうわけで、ごく一部ではありますが、エンジニアについて紹介していきます゚+.(◕ฺ ω◕ฺ )゚+.


--- 朝のラジオ体操 ---

$サイバーエージェント 公式エンジニアブログ

座り仕事がほとんどなので運動不足になりがち。
朝のラジオ体操で健康も気にする素敵なエンジニアさんたちです。


--- デスクを覗いてみた ---

デスク紹介とか1回やってみたかったんですよねー。

1人目

$サイバーエージェント 公式エンジニアブログ

私のデスクです。普通です。小汚いです。。

2人目

$サイバーエージェント 公式エンジニアブログ

すごい圧迫感。威圧感?
サンダーボルトを含め、5台ディスプレイとiPadが連なっています。
絶対全部活用できない。。
キョロ(ω・`))(´・ω・`)(( ´・ω)キョロ、、、首を痛めそうです。。

3人目

$サイバーエージェント 公式エンジニアブログ

とにかくフィギュアがすごい。。
初めて見た時は圧倒されすぎて、話すときこの話題を切り出すか戸惑ってしまいました。
他にもフィギュアを置いている方はいっぱいいますが、本当にこれはすごい。
総額20万はくだらないそうです。地震が心配だなぁ。。


--- 外国人さんがいっぱい ---

外国人さんがいっぱいいるフロアがあります。
男性ばかりなにの、なんか華やか、かっこいい。

$サイバーエージェント 公式エンジニアブログ

ゲームの基盤を支えてくれているかっこいいお兄さま達です!

$サイバーエージェント 公式エンジニアブログ


こちらクロードさん。Gmailを見ております(´・ω・`)

$サイバーエージェント 公式エンジニアブログ


ジョナサンさんは、Node.jsの中心メンバーとしてNode.jsの先生やフレームワークの開発を行なっています(・∀・)


--- エンジニアプロデューサー育成会議 ---

$サイバーエージェント 公式エンジニアブログ

うちでは、エンジニアも企画に関わることが本当に多いです。
「エンジニアプロデューサー育成会議」(前、ポイントすすむくん)とゆうものがあり、
社長に企画案・改善案を出したりしながら、社長からプロデューサー業を学ぶことができるんです。
実は、私もこの会議に参加させて頂いており、同期とアイディア出しの真っ最中です!

2年で2万の企画
エンジニアプロデューサー育成会議

その他にもエンジニアが企画に関わる機会がたくさんあります。ちょっと古い情報にはなりますが、以前エンジニアブログでのエントリーがあるのでそちらをご参照ください。
サイバーエージェントの技術者が企画に関われる制度まとめ


--- 勉強会への取り組み ---

エンジニアといえば、、、勉強会!

$サイバーエージェント 公式エンジニアブログ

SUF (Skill Up Friday)と称して毎週金曜日、全職種を対象に勉強会を行なっています。
違う職種の人でも興味があれば気軽に参加できる勉強会です。
過去にはGitやレベルデザイン勉強会などが行われました。

(エンジニアブログ編集者注:SUFに関しては今後エンジニアブログでも定期的に取り上げたいと思っています!)

$サイバーエージェント 公式エンジニアブログ

SUFは大人数での勉強会になりますが、もちろん少人数での勉強会はあちらこちらで行われています。


ちょっとはエンジニアのことをわかってもらえたでしょうか。
そんなエンジニアにキラキラ女子は、、、(うっとり

$サイバーエージェント 公式エンジニアブログ


ではでは

photo by @79yuuki

第6回テックヒルズでアメーバピグにおけるJenkinsの活用例を発表しました。

$
0
0

はじめまして。
アメーバ事業本部でアメーバピグの開発/運用を担当しております、丸山と申します。

去る6月18日、CROOZ株式会社主催の勉強会テックヒルズにて第6回Jenkinsをテーマにして開催されました。そこでアメーバピグにおけるJenkinsの活用事例について登壇の機会を頂きました。

$サイバーエージェント 公式エンジニアブログ

$サイバーエージェント 公式エンジニアブログ


当日は、すでにローンチして2年以上経った状態でのアメーバピグにおいて、

* コード品質管理
* バッチ制御
* オペレーションの自動化

の3点をJenkinsを利用して如何に実現してきたかを実例を交えて話させていただきました。
が、あまりにも内容が赤裸々すぎたので後で会社から怒られないか若干心配です。

なお、発表時の資料をslideshareに上げておりますので、これからJenkinsを導入する方にとってで少しでも参考になれば幸いです。



ちなみに、CIにしろバッチ処理にしろ、Jenkinsを後になってから入れるのははっきり言って茨の道でしかないので、もし導入を検討されているのであれば一日でも早く導入すると幸せになれますよ!

参加者のみなさま。登壇者のみなさま。テックヒルズスタッフのみなさま。
本当にありがとうございました!おつかれさまでした!

最後にもう一度、、、Jenkinsははじめからいれよう!僕との約束です!(キリッ

出、出、出〜ameba画像配信奴〜!!

$
0
0

はじめまして。インフラ所属の@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/

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

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

Velocity 2013 レポート

$
0
0

Velocity 2013


ちょりーっす!コミュニティ部門でWebデベロッパーをしています石本(@t32k)です。今回は6/18-6/20、米国のサンタクララで開催されたVelocity 2013のレポートを書いてみるよ。

Velocityは『ハイパフォーマンスWebサイト』の著者でも有名なSteve Souders氏が2008年から開催している、Web Performance(フロント、バックエンド問わず), Web Operationsなどを幅広く取り扱ってるカンファレンスです。また同名のカンファレンスが、ニューヨーク、ロンドン、北京でも開催されており、まさしく世界的なカンファレンスと言ってもいいでしょう。
『ハイパフォーマンスWebサイト』を読んだ時から、私にとっていつかは行きたいと思ってた憧れのカンファレンスだったので、3日間興奮しまくりでした。その中でも特に印象的だったTwitter社のMarcel Duran氏のセッションを紹介したいと思います。

- Velocity 2013 - O'Reilly Conferences, June 18 - 20, 2013, Santa Clara, CA

Avoiding Performance Regression at Twitter



TwitterのWeb-CoreチームでパフォーマンスエンジニアをしているMarcel Duran氏は問題を抱えていました。バグフィックスや新機能を追加し新しくリリースした時に、パフォーマンスの低下が見受けられました。困った問題です。これらの簡単なソリューションはCTRL+Rを押してリロードすれば早くなります(冗談です)。

通常であればMonitorして、不具合があれば修正をBuildし、Testし、Deployし、Usersに届けるといった典型的な開発サイクルをとるでしょう。しかし、新しい機能追加、バグフィックスごとに多くのブランチが存在します。とあるケースで100msパフォーマンスが低下したとしましょう。この原因を探すことは干草の山から一本の針を探すようなもので、不可能に近いです。

Tools


そこで、パフォーマンスを理解するために便利なツールが多く存在しますのでいくつか紹介します。

Cuzillion
CuzillionはSteve Souders氏が作ったツールで、ページで読まれているコンポーネントがどのように相互作用するのか確認できます。外部JS、外部CSS,画像などのコンポーネントをどのような順番で読み込ませるのか、組み合わせテストすることできます。

YSlow
YSlowはページのパフォーマンス評価を測定してくれるツールです。Chromeであれば拡張機能をインストールし、計測したいページでYSlowを実行するだけで、パフォーマンス評価を項目ごとにレポートしてくれる便利なツールです。

HAR
HARはHTTP Archiveファイルと呼ばれるもので、ページで読み込まれるコンポーネントのHTTP通信のログをJSONファイルでまとめたものです。ChromeやFirefoxなどのNetworkタイムラインを見ることができる開発者ツールでHARファイルを書き出すことができます。また、PhantomJS、Charles、WebPagetest、HTTPWatch、Fiddlerなどのアプリ、サービスでもHARを取得することができます。

WebPagetest
WebPagetestはパフォーマンスを計測してくれるWebサービスです。サイトを訪問してみればわかると思いますが、テストするロケーションを世界各地から選択することができ、またテストするブラウザーも組み合わせることで様々なパフォーマンステストを行うことができます。

また、First View、Repeat Viewでのウォーターフォールチャートの作成、Start Renderタイムの表示、PageSpeedスコアの表示、スクリーンショットの作成、ビデオ比較など非常に高機能なWebサービスです。

Show Slow
Show Slowは各ページのYSlowグレード、 PageSpeedスコア、dynaTraceランク、WebPagetestの指標を記録・公開するWebサービスです。一度サイトから計測したいページのURLを入力すれば、24時間毎に自動的に計測しつづけてくれます。

$ npm install yslow -g


Node ModuleのYSlowを使えばコマンドラインから使用することができ、それらの結果をShow SlowのBeacon URLで叩けば、任意のタイミングで記録することも可能です。

Continuous Integration

Yahoo! Profileでは継続的開発において、Unit, Integration, Acceptance, Smoke, Regression, Ninja などのさまざまなテストを行なっています。

しかし、Webパフォーマンスに関してはどうでしょうか?全くもって皆無です。デプロイしてユーザーに届いてからWebPagetestでパフォーマンス低下を発見できても時既に遅し、後手後手の対応を取らざるを得ません。

そこで、PhantomJSというものを使います。PhantomJSはHeadless WebkitブラウザーでJavaScriptから動かすことが可能です。

--------
クリエイターズブログでもPhantomJSを使ったテストについて書かれています。
- PhantomJSを使ったスマホサイトテストの自動化(前編)|1 pixel
- PhantomJSを使ったスマホサイトテストの自動化(後編)|1 pixel
--------

$ phantomjs yslow.js http://yslow.org


PhantomJSでYSlowを動かすモジュールも提供されていますので、これをJenkins上で動かすことにしましょう。

--------
前回のエンジニアブログでもJenkinsについて書かれています。
 - 第6回テックヒルズでアメーバピグにおけるJenkinsの活用例を発表しました。|エンジニアブログ
--------

-f, --format {format}
(json|xml|plain|tap|junit)


YSlowで吐き出す結果のフォーマットのデフォルトはjsonですが、TAP(Test Anything Protocol)を指定しましょう。


あらかじめ、JenkinsのTAP Pluginをインストールしておきます。

こうすることで、YSlowで生成されたテスト結果(TAPファイル)をJenkins上で良い感じにレポーティングしてくれます。

phantomjs yslow.js --info all --format tap --threshold '{"overall": "B", "ycdn": "F", "yexpires": "F", "ydns": "D"}' --ua "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5" http://yslow.org > yslow.tap

フリースタイルのジョブを新規作成し、上記のようなシェルを実行すればOKです。

--infoオプションは吐き出すログの種類 (basic|grade|stats|comps|all)です。

--thresholdオプションはしきい値([0-100]|[A-F]|{JSON})で、JSONを書くことで細かい設定が可能です。一般的にはUses ContentDelivery Networkなどの項目をクリアすることは難しいかもしれないので、そうゆう項目はFランクのままでもテストがOKになるようにこのオプションで指定します。

--ua は文字通りUser Agentを指定するもので、スマホ専用サイトの計測などに便利です。


TAP Pluginのレポートで上記のように表示されます。完璧ですね。

このようなプロセスをDeploy前に組み込むことで、問題があれば再度修正し先手先手の対応が可能となります。

High Performance

ただ、問題なのはYSlowの評価はわりと大雑把というか読み込み時間などの細かな変化をレポーティングすることはできません。世の中にはWebパフォーマンスを評価するうえで様々な指標が存在します。

- TTFB (Time To First Bite)
- Start Render
- Page Load
- domReady
- AFT(Above the Fold Time)
- Speed Inedx

一般的な指標は上記のようなものですが、扱っているサービスごとに重要な指標というのは変わってきます。Twitter社ではTTFT(Time To First Tweet)最初のTweetが表示されるまでの時間に着目しています。

この数値を出すために、WebPagetest APIを利用し、なおかつNode.jsで利用できるようにラッパーを作成しました。

 - WebPageTest API Wrapper


さらに、Peregrineというツールを使い、dev, staging, prodなど環境ごとにWebPagetestを走らせ、レポーティングを可能にしています。Peregrineは近日中にはオープンソースとして公開する予定です。


このような試みより、パフォーマンス低下に怯えることなく安全・安心に新機能追加・バグフィックスのデプロイすることができるようになりました。

その他参加セッションリスト

フロントエンド多めです。

Tue 18 Jun
Avoiding Performance Regression at Twitter / Marcel Duran (Twitter Inc.)
本記事のセッション。一発目からテンションだだあがりでした!

Bits on the Wire / Mark Nottingham (Akamai)
TCP/HTTP/DNSなどネットワークの基礎から応用まで丁寧に解説。

Speeding Up Your Mobile HTML5 Experience / Maximiliano Firtman (ITMaster Professional Training)
高速化のためのTipsやToolsを広く網羅してる内容。

A Picture Costs a Thousand Words / Guy Podjarny (Akamai)
画像形式ごとの仕組みやメリット・デメリットを解説。

Wed 19 Jun
Keynotes

Conquering The Uncanny Valley: Making Web Apps As Smooth As Native / Andrew Betts (FT Labs)
便利なモバイルフレームワークを多く作ってるFT Labさんの実用的なTips集。

Optimizing JavaScript Runtime Performance for Touch / Stephen Woods (Yahoo!)
JavaScript実行の最適化とか

The Curious Case of Dust Javascript and Performance / Veena Basavaraj (LinkedIn)
LinkedInでJSテンプレート(Dust.js)を採用した経緯について。

The CSS and GPU Cheatsheet / Colt McAnlis (Google)
GPUレンダリングを正しく理解するための各種レイヤーの説明

A Baseline for Web Performance with PhantomJS / Wesley Hales (Apigee), Ryan Bridges (Turner Broadcasting/CNN Digital)
PhantomJSとloadreport.jsを使ったパフォーマンスレポート作成

HTTP/2.0: What's Happening, and What's Next?
次期HTTP仕様に関してのパネル・ディスカッション

Thu 20 Jun
Keynotes

The Top 5 Performance Shenanigans of CSS Preprocessors / Nicole Sullivan (Stubbornella)
CSS プリプロッセー使用でよくあるミスをパフォーマンスの観点から。

Emerging Language Tools to Track JavaScript Quality and Performance/ Ariya Hidayat (Sencha)
Esprimaの使い方とか

Benchmarking the Front End: Expanding What Performance Means and How to Track it /Emily Nakashima (ModCloth), Rachel Myers (GitHub)
Single-Page Appのパフォーマンス計測に関して取り組んだ事例、必見!

Performance Monitoring: Synthetic vs RUM / Jon Fox (Torbit)
統合計測とリアルタイム計測の比較・使い分けを分かりやすく解説。

Top 10 WPO Disasters: Don't Let This Happen To You / Joshua Marantz (Google)
パフォーマンス最適化に際し、陥りがちな落とし穴10個!

Improving 3rd Party Script Performance With IFrames / Philip Tellis (SOASTA, INC)
ノンブロッキングなJS読み込みパターンについての解説。

Enough With The JavaScript Already! / Nicholas Zakas (Box)
そのJavaScript本当に必要ですか?

感想


『ハイパフォーマンスWebサイト』で、一般的にパフォーマンスの原因がフロントエンド:バックエンドで 8:2の割合であると述べられてから、フロントエンドのパフォーマンス改善は重要視されてきており、それに対する改善策なども多く行われてきました。しかし、海の向こうのフロントエンドエンジニアはそれだけでは満足せず、改善を行った結果をより正確に、より分かりやすく他の職種の人に共有する努力をしていると感じました。

このセッションに限らず、ほかのセッションでもPhantomJSとloadreport.jsを使用しレポーティングの自動化を行なっていたり(またCIサーバに組み込んだり)、Single-Page Appのパフォーマンス計測では、従来のNavigationTiming APIが意味をなさないので、Google AnalyticsのUser Timings機能を使い、独自の評価軸を設けている事例などがありました。

Front-End Opsという言葉が出てきてるように、私はDeveloperだからOperationのことは知らない・分からない。私はフロントエンドだからバックエンドのことは知らない・分からない、と言っているようであれば確実に取り残されてしまう業界であると痛感するとともに、非常に刺激を受けた良いカンファレンスでした。また来年も行きたいです。

Velocityでの資料は以下のページに集約されていく予定なので、みなさんもぜひチェックしてみてください。

- Speaker Slides: Velocity 2013

社内勉強会制度「Skill U Friday」

$
0
0
皆様はじめまして。
アメーバ経営本部で開発支援を行っている織田と申します。

今回、Ameba事業本部で執り行っている社内勉強会「Skill U Friday」についてご紹介さし上げます。
アメーバでは、社内外のノウハウや最新動向を持ち寄り部門や職能を越えて勉強会を定期開催しています。

サイバーエージェント 公式エンジニアブログ

現在アメーバには様々な部門があり、
それぞれの部門のプロジェクトに配属された開発者の数も1,000人※1を超えています。
Skill U Friday は、アメーバ全体の技術・品質の向上と
開発に携わる社員1人1人のスキルアップの一助となる機会のうちの1つとなります。

昨年の夏より取り組み、2013年5月時点で計40回を越えました。
これら過去に行われた勉強会は、資料と映像を記録し
新たに配属された社員や、当日参加できなかった社員でも
参照できるようにしております。
今この記事をご覧の方で将来サイバーエージェントで働く機会がありましたらご覧ください。

さて、Skill U Friday とはどのようなものか、具体的にご案内致します。

※1・・・正社員、契約社員、派遣社員、業務パートナーを含む

■概要
基本的に金曜日※2 に開催する部内の情報共有会、勉強会です。
対象範囲はアメーバ事業本部に所属しているメンバーと関連する部門またはグループ会社に所属する参加希望者で、
普段、開発やメンテナンスで多忙な開発者が、この機会では部門承認で参加できるという機会です。

形式やジャンルは一切問わず、自身の専門分野以外をテーマとする勉強会でも自由に参加することができます。
・講義形式
・ワークショップ形式
・ハンズオン形式
など形式は様々です。

また、勉強会開催時に参加対象者は指定しますが
ライブ配信を社内限定で行っており、
終了後、録画版も配信しています。
そのため、希望者はいつでも映像を見ながら参加することが可能です。

※2・・・状況に応じて開催日程を調整しています。

■方針
勉強会の主催は、部門推薦による登壇や立候補による登壇が基本ですが、
部門全体の経営方針に則り、最適な技術・知識の方向性を選定し
その分野で実績がある、または精通していることを前提としています。

テーマの選定、方向性は
アメーバ内外の動向を探り、
・今後必要となるであろう新規分野
・現在必要とされる分野
・見直しが必要な分野
に分けて優先度を決めて決定しており、
これらの決定に際して、技術の統括部門と協議し
決定する機会もあります。

また、テックレポート※3 をはじめとする
サイバーエージェント発のあらゆる情報発信と連携を深め
より高品質な技術・品質の向上につとめ
サービスに還元できるナレッジ・ノウハウという企業の資産の組織化を運用方針の主軸としています。

※3・・・http://ameblo.jp/cair/theme2-10054625217.html

■目的
Skill U Friday は、その運用にあたって
より高く、安定した技術でサービスを多く提供できるよう「知識創造企業※4」としてAmeba全体の知識や技術力を組織化し、暗黙知と形式知のスパイラルを形成することを目的としています。
SECI モデルをベースに知識を体系化し、それぞれの「場」を提供し
現場の声、経営の方針から各テーマの知が現在どの位置にあるかを把握し、今後の方向性を定めて各テーマ毎にマネジメントしていく形です。

サイバーエージェント 公式エンジニアブログ

勉強会の開催にあたって、開催条件や形式を絞らずに行っているのは
テーマによって、形式知化すべきか暗黙知化すべきかのフェーズをはかり、最適な形で場を提供するためでもあります。

また、Ameba全体という範囲を対象として開催している背景には、
技術指向や技術レベルの分散を防ぎ、社内連携を強める意図があります。
前述の通り、Amebaには1,000人超の開発者が所属していますが、
Amebaはには大きく4つの分野に分かれた部門があり、その部門の中に各事業部が分かれ、プロジェクトがそこに所属する形で
開発者が事業に携わっています。
よって、1つのプロジェクトに所属する同じ職能のメンバーは1人~5人くらいといったケースが発生します。
各事業部や部門に共有体制やサポート体制があり、それぞれが機能していますが
Ameba全体の方向性や体制を整え、技術戦略を立てるとなると
文化として、Ameba全体で職能同士の繋がりや情報共有体制を整えておく必要性があります。
予め想定されるプロジェクト別の技術力の格差や、方向性の分散といったリスクを防いだ状態で、
目的を果たす事が重要であると考えます。

■事例
Skill U Friday では、幅広いジャンルを取り扱っております。
これまで、インフラからUI・UX、プロジェクトマネジメントや統計にいたるまで様々な形式で開催されております。
ここではその一部をご紹介さし上げます。

サイバーエージェント 公式エンジニアブログ

【インフラ・DB】
・NoSQL Conference FeedBack
・Introduction to Cassandra
・Ceph the future of strage
・オープンソースRDBMS勉強会(MySQL/PostgreSQL/MariaDB)

【テスト・自動化・開発環境】
・JMeter を使った性能検証の講習会
・Chromeデベロッパーツールでパフォーマンス改善
・Git講座(入門・基礎・応用)
・Java用IDE IntelliJ IDEA FB会
・Chrome DevTools.next
・Jenkins導入から自動ビルド&自動配布までの設定方法について
・Node.jsのテスティング

【ミドルウェア】
・PHPプロジェクトのノウハウ共有
・Scala入門・ノウハウ共有
・レコメンドエンジン入門

【フロントエンド】
・Frontrend シリーズ※4 社内講演
・オフラインWebアプリケーションのつくりかた
・Backbone.js入門講座
・Require.js を利用した AMD の実践とハンズオン
・Zepto ≒ jQuery
・2013年 html5 の api 動向について
・「Klepto」を使ったJavaScript開発手法の紹介

【UI/デザイン設計】
・運用から見たUI改修(Ameba社内事例)
・ユーザーを引き込むUIデザイン考

【統計/データマイニング】
・単純パーセプトロンって何?~線型識別器の基本のき~
・今日からあなたもアナリスト!~Rで学んで実践するデータマイニング~
・Cyberagent マーケティング&アナリティクス勉強会※5 シリーズ
など他にも様々な勉強会が開催されております。

※4・・・http://frontrend.github.io/
※5・・・http://ameblo.jp/ca-marketing/

現在では、さらにターゲットの差別化を行い
コンテンツの最適化を進めて計画しています。

■今後
参加した社員より、
・部門を越えた同じ職能の社員同士で情報交換ができる機会である
・後日復習できる環境があるのでペースに併せられる
・プロジェクトの事例を知る事ができて刺激がある
などの声もあり
今後も Skill U Friday を拡充し、
より高品質なサービスを生み出せる環境を築いて参ります。

Google IO 2013 report part.1

$
0
0

I am Patrick Boos. I am a developer at CyberAgent, Inc.

Google IO Sessions
It was a great opportunity for me to go to Google IO in San Francisco in May 2013. I have been able to meet great people and learn about the newest trends and technologies. As a Android Developer I was of course interested about everything related to Android. For that reason I mainly followed the Android track and visited many great sessions. Afterwards I will share the points from those sessions that got me interested most. I learned two years ago at my last Google IO, that there is always an empty seat somewhere in the front. I know that by sharing this secret I might risk that this won’t be true anymore next year ;-).
I hope you understand, that I can not share everything said at Google IO here. There is just too much and I do not have the time to write about all of that. But I would like to share a few things that I liked most:

> New Build System for Android
The new build system which uses gradle is very interesting. It is what I have been waiting for for a long time. I have started using Maven because that helped me to accomplish my tasks better. Gradle is not finished yet, but on a very good way to make me switch to it from maven. Gradle seems to be a lot more flexible than maven, but still simpler than maven.

> Android Studio
Since I did the switch to Intellij IDEA last year already, I was very happy to see this change. I recommend everyone to try out the new Android Studio already. You will not regret switching to it. I would never go back to eclipse again.

> Google Play Services update
It is great to see that Google supports us developers by adding new APIs to Google Play Services. This way we can target even old phones without having to wait for them to be updated with a newer Android version.
Those include: Maps v2 (since December), Fused Location Provider, Geofencing, and Activity Recognition (walking, biking, …), Google+ SignIn, GCM updates and lastly APIs for games which includes Game State sync, Leaderboards, Achievements and Multiplayer.

Google IO Sandbox
Besides the sessions there was the Sandbox where many well known companies where present and where one had the chance to talk to many great developers from Google or other companies. Since I could watch the sessions from Japan as well, the Sandbox was a focus for me on the last day of Google IO. I noticed that this was a great decisions because I was able to talk to engineers that were a lot more experienced than I am. So could I learn a lot more about how other engineers approach and solve problems. I was able to talk to gradle developers and learn how I can use it for the tasks that I want to and how to extend or configure it to do the things I want it to do.

Meetups
But there was more than just Google IO. San Francisco offers a lot of great meetups that got me busy in the evenings. Anyone traveling to San Francisco I would recommend to check out meetups and go to as many as possible that are of your interest. I was able to go to 3 meetups and I have really enjoyed them. There were great presentation and especially the people that participated. I meet people that I have worked together over the internet.

Meeting People
You might have noticed already, that wherever I went I was able to meet people. And this is what I would recommend to everyone! If you go to a conference, spend all the free time meeting people! You won’t regret it. Of course you can learn from the presenters of the conference. And you should listen and learn from them. But you can learn a lot from the fellow attendees as well! Don’t miss that chance. If you go to the conference breakfast/lunch for example. Do not search for the empty table. Search for the most crowded table (which has still a seat open) and join it. Get to know the people at that table, ask questions, get to know them.

社内勉強会制度「Skill U Friday」

$
0
0

皆様はじめまして。
アメーバ経営本部で開発支援を行っている織田と申します。

今回、Ameba事業本部で執り行っている社内勉強会「Skill U Friday」についてご紹介さし上げます。
アメーバでは、社内外のノウハウや最新動向を持ち寄り部門や職能を越えて勉強会を定期開催しています。

サイバーエージェント 公式エンジニアブログ

現在アメーバには様々な部門があり、
それぞれの部門のプロジェクトに配属された開発者の数も1,000人※1を超えています。
Skill U Friday は、アメーバ全体の技術・品質の向上と
開発に携わる社員1人1人のスキルアップの一助となる機会のうちの1つとなります。

昨年の夏より取り組み、2013年5月時点で計40回を越えました。
これら過去に行われた勉強会は、資料と映像を記録し
新たに配属された社員や、当日参加できなかった社員でも
参照できるようにしております。
今この記事をご覧の方で将来サイバーエージェントで働く機会がありましたらご覧ください。

さて、Skill U Friday とはどのようなものか、具体的にご案内致します。

※1・・・正社員、契約社員、派遣社員、業務パートナーを含む

■概要
基本的に金曜日※2 に開催する部内の情報共有会、勉強会です。
対象範囲はアメーバ事業本部に所属しているメンバーと関連する部門またはグループ会社に所属する参加希望者で、
普段、開発やメンテナンスで多忙な開発者が、この機会では部門承認で参加できるという機会です。

形式やジャンルは一切問わず、自身の専門分野以外をテーマとする勉強会でも自由に参加することができます。
・講義形式
・ワークショップ形式
・ハンズオン形式
など形式は様々です。

また、勉強会開催時に参加対象者は指定しますが
ライブ配信を社内限定で行っており、
終了後、録画版も配信しています。
そのため、希望者はいつでも映像を見ながら参加することが可能です。

※2・・・状況に応じて開催日程を調整しています。

■方針
勉強会の主催は、部門推薦による登壇や立候補による登壇が基本ですが、
部門全体の経営方針に則り、最適な技術・知識の方向性を選定し
その分野で実績がある、または精通していることを前提としています。

テーマの選定、方向性は
アメーバ内外の動向を探り、
・今後必要となるであろう新規分野
・現在必要とされる分野
・見直しが必要な分野
に分けて優先度を決めて決定しており、
これらの決定に際して、技術の統括部門と協議し
決定する機会もあります。

また、テックレポート※3 をはじめとする
サイバーエージェント発のあらゆる情報発信と連携を深め
より高品質な技術・品質の向上につとめ
サービスに還元できるナレッジ・ノウハウという企業の資産の組織化を運用方針の主軸としています。

※3・・・http://ameblo.jp/cair/theme2-10054625217.html

■目的
Skill U Friday は、その運用にあたって
より高く、安定した技術でサービスを多く提供できるよう「知識創造企業※4」としてAmeba全体の知識や技術力を組織化し、暗黙知と形式知のスパイラルを形成することを目的としています。
SECI モデルをベースに知識を体系化し、それぞれの「場」を提供し
現場の声、経営の方針から各テーマの知が現在どの位置にあるかを把握し、今後の方向性を定めて各テーマ毎にマネジメントしていく形です。

サイバーエージェント 公式エンジニアブログ

勉強会の開催にあたって、開催条件や形式を絞らずに行っているのは
テーマによって、形式知化すべきか暗黙知化すべきかのフェーズをはかり、最適な形で場を提供するためでもあります。

また、Ameba全体という範囲を対象として開催している背景には、
技術指向や技術レベルの分散を防ぎ、社内連携を強める意図があります。
前述の通り、Amebaには1,000人超の開発者が所属していますが、
Amebaはには大きく4つの分野に分かれた部門があり、その部門の中に各事業部が分かれ、プロジェクトがそこに所属する形で
開発者が事業に携わっています。
よって、1つのプロジェクトに所属する同じ職能のメンバーは1人~5人くらいといったケースが発生します。
各事業部や部門に共有体制やサポート体制があり、それぞれが機能していますが
Ameba全体の方向性や体制を整え、技術戦略を立てるとなると
文化として、Ameba全体で職能同士の繋がりや情報共有体制を整えておく必要性があります。
予め想定されるプロジェクト別の技術力の格差や、方向性の分散といったリスクを防いだ状態で、
目的を果たす事が重要であると考えます。

■事例
Skill U Friday では、幅広いジャンルを取り扱っております。
これまで、インフラからUI・UX、プロジェクトマネジメントや統計にいたるまで様々な形式で開催されております。
ここではその一部をご紹介さし上げます。

サイバーエージェント 公式エンジニアブログ

【インフラ・DB】
・NoSQL Conference FeedBack
・Introduction to Cassandra
・Ceph the future of storage
・オープンソースRDBMS勉強会(MySQL/PostgreSQL/MariaDB)

【テスト・自動化・開発環境】
・JMeter を使った性能検証の講習会
・Chromeデベロッパーツールでパフォーマンス改善
・Git講座(入門・基礎・応用)
・Java用IDE IntelliJ IDEA FB会
・Chrome DevTools.next
・Jenkins導入から自動ビルド&自動配布までの設定方法について
・Node.jsのテスティング

【ミドルウェア】
・PHPプロジェクトのノウハウ共有
・Scala入門・ノウハウ共有
・レコメンドエンジン入門

【フロントエンド】
・Frontrend シリーズ※4 社内講演
・オフラインWebアプリケーションのつくりかた
・Backbone.js入門講座
・Require.js を利用した AMD の実践とハンズオン
・Zepto ≒ jQuery
・2013年 HTML5 の API 動向について
・「Klepto」を使ったJavaScript開発手法の紹介

【UI/デザイン設計】
・運用から見たUI改修(Ameba社内事例)
・ユーザーを引き込むUIデザイン考

【統計/データマイニング】
・単純パーセプトロンって何?~線型識別器の基本のき~
・今日からあなたもアナリスト!~Rで学んで実践するデータマイニング~
・CyberAgent マーケティング&アナリティクス勉強会※5 シリーズ
など他にも様々な勉強会が開催されております。

※4・・・http://frontrend.github.io/
※5・・・http://ameblo.jp/ca-marketing/

現在では、さらにターゲットの差別化を行い
コンテンツの最適化を進めて計画しています。

■今後
参加した社員より、
・部門を越えた同じ職能の社員同士で情報交換ができる機会である
・後日復習できる環境があるのでペースに併せられる
・プロジェクトの事例を知る事ができて刺激がある
などの声もあり
今後も Skill U Friday を拡充し、
より高品質なサービスを生み出せる環境を築いて参ります。


PR: チャージのいらない電子マネー、QUICPay

$
0
0
ずーーっとチャージ不足の心配なし!お得なキャンペーンも実施中!入会はこちら。

lombokで快適Java生活

$
0
0

どうもこんにちは、社内ではJava嫌いで有名になってしまった oinume です。最近Javaに慣れすぎてむしろスクリプト言語が苦手になってきています。今回は「これがあればJavaでの開発もそんなにストレスないかもなぁ」と思える個人的な3種の神器のひとつである lombok を紹介します。

lombokってなに?

一言でいうとJavaの野暮ったいgetter/setterメソッドなどを自動的に生成してくれるソフトウェアです。例えば @Data アノテーションをつけて以下のようにメンバー変数を定義するだけで、lombokがgetter/setter/equals/hashCode/toStringのメソッドをコンパイル時に生成してくれます。

package sample;

import lombok.Data;

@Data
public class User {

    private int id;
    private String name;
    private String email;

    public static void main(String[] args) {
        User user = new User();
        user.setId(1);
        user.setName("oinume");
        user.setEmail("oinume@example.com");

        System.out.println(user);
        // --> User(id=1, name=oinume, email=oinume@example.com)
    }
}

どうでしょう?使ってみたくなってきませんか?

インストール

lombokはコンパイル時にメソッドなどを生成するため、EclipseなどのIDEを使っている場合はインストールが必要です。JREがインストール済みの環境であれば、lombok のサイトから lombok.jar をダウンロードしてダブルクリックすればインストーラーが立ち上がるので、下記のようにEclipseを選択して下さい。

eclipse.iniに下記の行が追加されていれば問題なくインストールされています。

-javaagent:lombok.jar
-Xbootclasspath/a:lombok.jar

また、実際にJavaプロジェクトから@Dataなどのlombokのアノテーションを使うにはpom.xmlなどに以下の依存関係を追加しておいて下さい。

pom.xml

    <dependencies>
        <dependency>
            <groupid>org.projectlombok</groupid>
            <artifactid>lombok</artifactid>
            <version>0.11.8</version>
        </dependency>
    </dependencies>

この設定が完了した状態で先程の User.java をEclipseで表示すると右側のOutlineに自分では定義していないgetter/setterメソッドなどがあることが確認できると思います。

なお、今回掲載したソースコードはGitHubに上がっているので、これをcloneすればすぐにlombok を試せます。

もう少し詳しく

lombokでは @Data アノテーションをつけると、getter/setter以外にもおなじみの

  • toString()
  • equals()
  • hashCode()

メソッドも併せて定義してくれます。例えば「getter だけを定義したい」というような時は、下記のように @Getter アノテーションを使います。

package sample;

import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor
public class User2 {
    @Getter
    private int id;
    @Getter
    private String name;

    public static void main(String[] args) {
        User2 user2 = new User2(1, "oinume");
        System.out.println("name = " + user2.getName());
    }
}

@DataはAll in oneなアノテーションだと思ってもらえればよいでしょう。lombokのfeaturesには使用可能なアノテーションが全て記載されており、それをつけた場合にどういうコードが生成されるかも書いてあるので興味のある方は読んでみて下さい。(@Delegateや@SneakyThrowsなど便利そうなアノテーションがあります)

lombokで生成されたコードが見たい

コンパイルされたクラスファイルをデコンパイルしてもいいのですが、もっと簡単な方法があります。

java -jar /path/to/lombok.jar delombok -p src/main/java/sample/User.java

を実行することで、lombokを通したあとのコードが出力されるので、lombokがどのようなコードを生成しているかがわかります。先ほどのUser.java の場合は以下のように出力されました。

// Generated by delombok at Fri Jun 28 23:00:50 JST 2013
package sample;

public class User {
    private int id;
    private String name;
    private String email;

    public static void main(String[] args) {
        User user = new User();
        user.setId(1);
        user.setName("oinume");
        user.setEmail("oinume@example.com");
        System.out.println(user);
    }

    @java.lang.SuppressWarnings("all")
    public User() {

    }

    @java.lang.SuppressWarnings("all")
    public int getId() {
        return this.id;
    }

    @java.lang.SuppressWarnings("all")
    public String getName() {
        return this.name;
    }

    @java.lang.SuppressWarnings("all")
    public String getEmail() {
        return this.email;
    }

    @java.lang.SuppressWarnings("all")
    public void setId(final int id) {
        this.id = id;
    }

    @java.lang.SuppressWarnings("all")
    public void setName(final String name) {
        this.name = name;
    }

    @java.lang.SuppressWarnings("all")
    public void setEmail(final String email) {
        this.email = email;
    }

    @java.lang.Override
    @java.lang.SuppressWarnings("all")
    public boolean equals(final java.lang.Object o) {
        if (o == this) return true;
        if (!(o instanceof User)) return false;
        final User other = (User)o;
        if (!other.canEqual((java.lang.Object)this)) return false;
        if (this.getId() != other.getId()) return false;
        final java.lang.Object this$name = this.getName();
        final java.lang.Object other$name = other.getName();
        if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
        final java.lang.Object this$email = this.getEmail();
        final java.lang.Object other$email = other.getEmail();
        if (this$email == null ? other$email != null : !this$email.equals(other$email)) return false;
        return true;
    }

    @java.lang.SuppressWarnings("all")
    public boolean canEqual(final java.lang.Object other) {
        return other instanceof User;
    }

    @java.lang.Override
    @java.lang.SuppressWarnings("all")
    public int hashCode() {
        final int PRIME = 31;
        int result = 1;
        result = result * PRIME + this.getId();
        final java.lang.Object $name = this.getName();
        result = result * PRIME + ($name == null ? 0 : $name.hashCode());
        final java.lang.Object $email = this.getEmail();
        result = result * PRIME + ($email == null ? 0 : $email.hashCode());
        return result;
    }

    @java.lang.Override
    @java.lang.SuppressWarnings("all")
    public java.lang.String toString() {
        return "User(id=" + this.getId() + ", name=" + this.getName() + ", email=" + this.getEmail() + ")";
    }
}

まとめ

Scalaを使おう!

弊社の最近のDevOpsへの取り組み

$
0
0

はじめまして。Amebaでインフラを担当しています山口と申します。
某所ではリア充イメージ(?)の強い弊社ですが、所属するインフラ部門は男性100%で構成されている上、私は女性っぽい名前ながらも中年のおっさん(趣味は料理)でございます。すんません。


それはさておき、ご存じの方もいらっしゃるかもしれませんが、弊社ではオーケストレーションツールとしてChefを使っております。私は参加しませんでしたが、最近、ChefConf 2013も開催されたことですし、最近の弊社でのDevOps、特にその中でも一風変わったChefの使い方についてお伝えしようと思います。


EC2インスタンスをつくる


最近ではOpsWorksなんかもありますが、本稿執筆時点(2013年6月)ではまだまだ発展途上で、弊社がサービスを作る上で必要な機能が網羅されていませんでしたので、自前のChef Serverを利用しています。

Chefはサーバが起動してからの仕組みですので、これだけだとEC2インスタンスは自分で作成する必要があります。これはManagement Consoleの他、APIをたたくコマンド等でもできますが、これがなかなかめんどくさい...。

というわけで、knifeコマンドでChefからインスタンス作成に必要な情報を引っ張り出して、インスタンスを作るようにしています。


$ knife neoec2 list aws@account.name
Instance ID Name Public IP Private IP Flavor Image Security Groups Chef State
i-12345678 amzn-ami-2013.03.x86_64-ebs.ca t1.micro ami-1e3e3212 default, make-ami ng stopped
i-23204932 cyberagent-app001 x.x.x.x 192.168.1.20 m1.small ami-f4f42123 default, app, http ok running
i-230423a2 cyberagent-db001 192.168.1.21 m1.small ami-f4f42123 default ok running

$ knife neoec2 create server001


knifeにはknife-ec2というプラグイン(Apache License 2.0)が既にありますが、こちらは引数でインスタンス作成に必要な情報を渡す必要があったり、複数のAWSアカウントで利用するのが難しかったりします。

ですから、弊社ではこれを一部参考にする形で、インスタンス作成プラグインを自前で作成(Closed License)しています。
弊社で使っているプラグインの主な特徴は以下の通りです。


  • ChefのAttributeからインスタンス作成に必要な情報を取得

  • 複数AWSアカウントに対応(Attribute内で使うAWSアカウントを選択)

  • AMIからのインスタンス作成時にrootボリュームの拡張や追加EBSボリュームの作成に対応

  • 起動後のインスタンスでChef Clientを自動実行


そのため、例えば追加ディスクが必要なDBサーバを作成する場合であっても、1コマンドでEBSの作成をして、さらにChefからファイルシステムを作成してマウント(必要であればRAIDも)して、自動でお目当てのサーバを作ることができます。


あんまり変わり映えしないですね...。
次はもう少し事例が少なそうな内容を


ChefのCookbookから監視設定を自動生成


Chefを使ってセットアップ、例えばApacheをインストールする場合はApacheがインストールされるCookbookを使います。これらのサービスに関わるCookbookに対し、監視に必要な情報、例えばTCPで特定のポートを監視するとか、特定のプロセスの生存を監視するとかのメタ情報を埋め込んでおけば、このCookbookを使った時点でそのサーバの監視対象が判ることになります。


先のApacheの例だと

  • TCP:80で応答があること

  • "/"宛にHTTPリクエストを発行すると200 OKのレスポンスがあること


この2つの監視メタ情報を入れておきます。

同様にその他のCookbookに対しても監視メタ情報を入れていくと、標準化されたCookbookを選択していくだけで、監視設定を生成するために必要な情報があつまります。で、このまとまった情報を取得できるWebAPIを作ってあるので、以下のようにすると監視設定が取得できるようになっています。


$ curl http://chef-server.address/api/generate -X POST -d "type=icinga" -d 'targets=group1/*' -d 'environment=prd'
(監視設定がずらずら...)



typeには「icinga」が入力されていますので、Icinga(Nagios亜種)の設定が出力されます。ここを同じく弊社がよく利用しているMuninなんかにすると、Munin用の設定が出力されます。curlで取れる内容なので、teeとかすれば設定ファイルとして保存することができます。


まとめると...



  • 標準化されたCookbookが存在するミドルウェアなら

  • どんな組み合わせ方で、何台のサーバを構築しても

  • サーバの構築の自動化と、それらを監視する監視サーバの設定の自動生成

  • 特にクラウド(AWSなど)を利用している場合は、サーバの準備も自動化


ができます。


弊社では1つのサービスあたりを数十台から数百台で構成することが多いですが、その位の台数なら、使い慣れたミドルウェアを利用しているサービスであれば、その気になれば一人で一日で作ることも可能です。

弊社には自前のプライベートクラウドがありますが、こちらでもAWS同様の仕組み化することが可能です。

HBaseCon2013参加レポート(前編)

$
0
0

こんにちは。アメーバでR&Dエンジニアをしている梅田と申します。

2013年6月13日に開催されたHBaseCon2013に参加してきましたのでレポートさせていただきます。HBaseConは、Apache HBaseの貢献者、開発者、管理者およびユーザのためのコミュニティイベントで、年1回開催されています。

今回はサンフランシスコのマリオット・マーキースホテルが会場で、講演は4トラック構成になっており、参加者は興味のあるものを選択して聴講していきます。

全てを紹介することはできませんが、今回は興味深かったセッションについて、前編、後編に分けていくつか紹介させていただきます。前編は、私、梅田がお送りします。


なお、当日の発表資料は、こちらの各セッションのリンクからダウンロードできます(2013年7月末時点、一部資料がアップロードされてません)ので、興味の有る方は是非どうぞ。

それでは、早速セッションの紹介に移りたいと思います。私は、Facebook、Yahooの中の人のセッションを紹介します。長文ではありますが、とても興味深い内容だと思いますので、是非最後までご覧ください。


HBase use cases at Facebook
Liyin Tang, Software Engineer, Facebook & HBase PMC Member

Facebookは、大規模なデータ処理の基盤としてHBaseを利用しています。
今回のセッションでは、次の3点についての説明がありました。
 (1) Tips for boosting performance
 (2) Elastically scale HBase in an online fashion
 (3) HBase Disaster Recovery Plan: Replication and Backup
Tips for boosting performaceでは、6つのTipsを紹介していました。
参考になるものも多かったのでここで紹介したいと思います。

 ① Keep the data local

facebook_per-region_data_placement

リージョン毎のデータ配置を工夫しているそうです。
 
 ② Read the local data
   ・Short circuit readを有効にする
   ・OSのページキャッシュを使う
   ・HBase L2キャッシュを使う

 ③ Reduce IOPS

reduce_IOPS

 ④ Throughput boost
   ・Memstoreのフラッシュを並列化
   ・hlogの多重化
   ・compactionスレッドの多重化

 ⑤ Performance boost with MR

facebook_performance_boost_with_MR

 ⑥ More IO Tuning

facebook_More_IO_Tuning



Multi-tenant Apache HBase at Yahoo!
Sumeet Singh (Yahoo!), and Francis Liu (Yahoo!)

Yahooでは、HBaseをマルチテナント化して使っているようです。
今回のセッションでは、次の4点が主な内容になります。
 (1) Security
 (2) Isolated Deployment
 (3) Region Server Group (HBASE-6721)
 (4) Namespace (HBase-8015)

Region Server GroupとNamespaceについては、HBaseの0.95.2でfixされるそうです。今後使う機会もあるかもしれませんので、ここで紹介したいと思います。

Region Server Group

yahoo_region_server_groups_overview

yahoo_region_server_groups_apis

リージョンサーバのグループを作ったり、リージョンサーバのグループにテーブルを割り振ったりできます。便利ですね。

Namespace

yahoo_namespace
ネームスペースがあると複数のサービスで使うときにテーブル名で困ることも少なくなりそうですね。



さて、次回は後編として、HBaseConに一緒に参加したR&Dエンジニアの飯島さんからレポートをお届けします。お楽しみに!

HBaseCon2013参加レポート(後編)

$
0
0

こんにちは、Amebaでカレーを探求している飯島です。
前編に引続きHBaseCon 2013のレポートです。

全部で40以上あるセッションのうち、15ほどを聞いたのですが、後編は次の3つのテーマに絞ってレポートさせていたただきます。

1. HBaseエコシステム
2. Kiji Project
3. Flume HBase sink

1. HBase エコシステム

General Sessionの中で出てきたHBaseエコシステムに触れると、今年のHBaseConのセッションのいくつかを紹介できるのでまずHBaseエコシステムについて書きます。



Hadoopエコシステムの1つとしてHBaseがあるわけですが、そのHBase自身のエコシステムも発展してきています。まず、SQLライクなクエリでHBaseにアクセスできるオープンソースプロダクトとして、ClouderaのImpala、SalesForceのPhoenix、Apache Drillといったものがあります。今回それぞれ本カンファレンスでセッションがありました。

Impala はデータサイエンティストがHadoop上のデータをインタラクティブに解析できることを目指したクエリエンジンで、HBase・HDFSの両方をサポートしています。高速に動作するようC++で開発されており、クエリがHiveQLがベースなので、Hiveを使っているなら馴染みやすいと思います。

Phoenix はJDBCドライバーを組み込んでいて、HBaseネイティブのスピードで動くようSQLを最適化しています。key filterを使えば1億ものRowにアクセスする場合でも低レイテンシで動作します。Salesforceが開発したものでこれもオープンソース化されています。

Apache Drill はApacheのオープンソースコミュニティで発展してきているものですが、バージョンもまだAlphaで上の2つに比べたらまだ発展途上な印象があります。

ちなみに、HortonworksのセッションであったようにHive HBase IntegrationによりHiveからHBaseにアクセスする方法もあります。こちらPhoenixのセッションで検証結果がありましたが、パフォーマンスはあまりよくないようです。

次に、監視システム周りでは、OpenTSDB、Hannibalといったものがあります。

OpenTSDB はHBaseをDBとしている監視ツールでサーバの各種メトリクスをグラフ化できます。Ganglia、Cacti、Muninなど従来の監視ツールではRRDsやFlat filesを使っていて何百台もサーバが監視対象だとスケールしにくいモデルでしたが、OpenTSDBはHBaseを利用しているので容易にスケールします。従来のPollingするタイプではなく、監視対象のサーバからHAProxyにPushするというのも特徴の1つです。

また今回、Hannibalのセッションはなかったですが、RegionのSplit状況をヴィジュアル化してHBaseクラスタの維持管理を容易にするHannibalというオープンソースプロダクトもあります。ちなみにScalaでできています。

その他として、LilyはHBase, Hadoop, Solrなどの大量データを統合的に管理できるようなOne-Stopなデータマネジメントプラットフォームで、APIなどでデータにアクセスできるようです。

また、HadoopやHBaseにログなどのファイルデータを連続的に流し込むFlumeもHadoopエコシステムの1つであり広い意味でHBaseエコシステムの1つとも言えるでしょう。

そして、HBaseを活用してデータの収集や解析、予測モデルなどを作れるフレームワークが出てきました。それが次に紹介するKiji Projectです。


2. Kiji Project

Kiji Projectはリアルタイムな Bigg Data アプリケーションのフレームワークとのことで、REST API、HiveやMapReduceなどのバッチ処理の仕組みなどいくつものコンポーネントがこのフレームワークに揃っていますこれを使うとデータの保存場所としてベストプラクティスでHBaseを利用できて、リアルタイムに大量データを使うようなアプリの開発が容易にできるそうです。



コンポーネントの1つとして、Kiji Schema はKiji Projectで最初に公開されたもので、Avroシリアライゼーションを使って構造化・非構造化データをHBase上で扱う仕組みを提供してくれるようです。

また、Kiji BentoBoxなるものを提供していて(プロダクト名などなぜ日本語(ローマ字)なのかは不明…)、これをインストールすると、HadoopやHBaseを直接インストールすることなく、HBaseミニクラスタ上で Kiji Schema を使うことができます。

…という説明をしても伝わりにくいので、15分でできるからぜひ使ってみてとのことなので、興味ある人は実際に使ってみる方が早いでしょう。 → Kiji BentoBox

また、Kiji ExpressというコンポーネントはPMML(Predictive Model Markup Language)ファイルをImportできるので、データサイエンティストが他のフレームワークで作った予測モデルでも取り込むことができるようです。

大量のデータからレコメンデーション、パーソナライゼーションなど何かしらモデルを表現するフレームワークとしても役立ちそうです。

3. Flume HBase Sink

私がFlumeを使ったプロジェクトに関わっているので、Flumeの
HBase sinkのセッションについて触れておきます。ログなど連続的に発生するデータをストリームとしてHDFSやHBaseに流し込むのに使えるのがFlumeです。


Flume Agentを経由してデータを転送したりするわけですが、最終的にHBaseに保存する方法はHBase sink と非同期版のAsync HBase sinkの2つがあります。どちらもデフォルトで用意されているserializerがあるのでそれを使って連続的に流れてくるデータをHBaseのデータ構造に変換できます。また、デフォルトのserializerをフォークして作り込むことでHBaseで利用したいデータ構造にカスタマイズして保存することもできます。

2つの違いとしては、HBase sinkはセキュリティ面でケルベロス認証をサポートしているのに対し、Async HBase sinkはサポートしていません。しかし、非同期で処理をするAsync HBase sinkの方が高スループットで大量データを扱うのにより適しています。

余談ですが弊社でも、アナリストが見る社内ツールでユーザの課金状況のリアルタイムな反映や、ログをリアルタイムにチェックするのにこのHBase sinkを使っていたりします。

ちなみに、Flumeのその他詳しい使い方も含め 公式ユーザガイド が凄く参考になります。


1dayのカンファレンスでしたが、とても濃厚で刺激的な時間を過ごすことができました。
それにしても先日のQConのレポートでも同じようでしたが、食事がホテルクオリティの朝・昼・晩の3食ドリンク付き、セッション後のパーティでもちろんお酒も用意されていてとても豪華なカンファレンスでした。きっとこの手のカンファレンスの参加費の半分くらいは食事代なのでしょうw お寿司が意外に美味しかったです。

(前半)OSCON 2013(Open Source Convention)行ってきた

$
0
0

こんにちわ。
今回は7月にオレゴン州ポートランドで行われたOSCON 2013(Open Source Convention)についてレポートしたいと思います。

参加したのはアプリケーションエンジニア4名です。
@koko1000ban(社内Ruby布教活動家)
@fuzzy31u(国境を超えるエンジニア)
@horimislime(にわかpythonista)
@waysaku(どやり開発プロセスエンジニア)

今回は代表してアメーバ事業本部の渡辺雄作(@waysaku)がレポートを取りまとめてみました。

まず会社としての海外カンファレンス参加への取り組みですが、私たちの所属するAmebaスマホコミュニティ部門では、今までは社内コンペ(テックレポートなど)のインセンティブとして海外カンファレンスに行くことがほとんどでした。

Webサービスを提供するエンジニアとして、視野を広げるためにも世界標準の技術やトレンド、雰囲気に肌で振れる機会を作ることは、長期的なエンジニアの成長、ひいてはAmebaの成長にとってプラスに働くのではという話に役員の賛同もあり、まずは数名で視察に行くことになりました。


そして直近で開催されるOSCON(OpenSourceConvention)に参加することにより、世界各国で提供されているOpenSourceプロダクトの開発者とコミュニケーションし、自分たちのプロダクトの改善と知見と刺激を得ようという考えです。
また単に足を運ぶだけではなく、今後のエンジニアの成長や育成を視野に入れ、組織的に海外カンファレンスへ参加することの意義を明らかにするという目的もあります。

ちなみにOSCON(Open Source Convention)は技術書でおなじみのOreilly主催で毎年行っているカンファレンスで、名前にもある通りオープンソースプロダクトに関連した最新の話を聞くことができる場になっています。



発表では実際に私達が使っているようなプロダクトの開発者から話を聞くことはもちろん、オープンソースに貢献している企業のイベントブースや、参加者が自由に集まってコーディングしたり議論できる”Hacking Area”が用意されていたりと、まさに開発者のためのお祭りのようなイベントになっています。

今回のレポートは前半でOSCONの雰囲気などをお伝えした上で、後半では基調講演の紹介と参加メンバーの気になるセッションを紹介したいと思います。

開催場所

oscon13_place

オレゴン州ポートランドのOregon Convention Centerで開かれました。
規模の大きいカンファレンスが開かれる会場のようで過去にはRailsConfなどもここで開かれたようです。
OSCON自体も、Keynoteが行われる大きな会場が1つ、セッションが開催される17部屋があり、かなり大規模なカンファレンスです。  

会場の雰囲気

らくがきボード

oscon13_board1

会場までの廊下には、いろんな会社と言語にあふれたボードがあり、祭りの空気を醸し出していました。


Amebaのイラストも書いておきました

リボン

oscon13_ribon

参加者同士の交流のきっかけとなるツールとしてリボンがおいてありました。
Clojureとλをつけてたら、たばこ場でλてなにって聞かれて不慣れな英語でラムダ計算を説明して微妙な顔されたのはいい思い出です。
また、DataNardをつけてる人が多かったので、何やってるのか聞いたら大学でもう何十年もデータのことを研究していると言ってました(何のデータかは英語力なくて詳しく聞けず…)  OSS Hackerだけでなく多彩な人が集まっていたように思います。

無限コーヒー、ランチ、ふれあい

OSCON_2013_1931
上のリボンとも関連して、ランチ時はテーブル毎にテーマの旗がたっていてディスカッションをするように設営されていたり、廊下にはコーヒーポットがおいてあったりなど、参加者同士で気軽に話し合える空気をうまくつくってました。
また、どこを歩いていてもスピーカーの人とすれ違う機会が多く、セッション良かったよ!と話しかけることをきっかけに色々と質問しやすかったです。

Session1
opscodeのJoshua Timbermanに感謝を述べるとともにcookbookの書き方について聞いた後の一枚


ブース

oscon13_booth1


OSCONでは、多数のスポンサーやStartupがブースを開く会場があり、そこを徘徊してノベルティを収集したり、実際に使用しているサービスの開発者から話を聞くのも楽しみのひとつです。

oscon13_booth2

また、Office Hourというスピーカーと直にディスカッションできる時間があり、ティム・オライリーと話し合えるなど、スピーカーと参加者の距離感がかなり近いカンファレンスだという印象が残っています。


後半は印象に残った基調講演や各セッションのピックアップを紹介したいと思います。

Scratchを使ったプログラミングキャンプ「Pigg Game CAMP」を開催します

$
0
0
今月21日(土)より、小学2年生~5年生を対象として
アメーバピグのキャラクターを使ったゲームを開発するワークショップ、
「Pigg Game CAMP」を開催します!


当ワークショップでは「Scratch」を使用して
2,3種類のゲームを開発します。

Scratchとは、MITメディアラボが教育用に制作した
子ども向けの言語で、パズルのようにプログラミングすることのできる言語です。
もちろん小学生でもプログラミングすることができ、
アルゴリズムを身につけるには最適な言語となっております。
Scratchはオンラインツールで誰でも無料で利用できるため、
ワークショップ終了後もご自宅で引き続き学習・開発が可能です。


また、ワークショップ当日は実際にアメーバピグを開発している
エンジニア社員との交流の時間なども設けています。

当社ではこうした取り組みによって、
将来的にエンジニアを目指す子どもたちの、
最初の機会を提供していければと思っています。

お子さんのいらっしゃるエンジニアの皆様も、
プログラミングを教えるきっかけとして、
当ワークショップへご応募いただければ幸いです。

[ご応募はコチラから]
http://techkidscamp.jp/camp/piggcamp/


Pigg Game CAMP開催概要
■開催日程
2013年9月21日(土)~ 23日(月・祝)10:00~16:00

■会場
東京都渋谷区 渋谷マークシティ17階(各線渋谷駅から徒歩約10分)
株式会社サイバーエージェント本社オフィス
http://www.ca-techkids.com/access/

■料金
35,000円(税込)

■定員
50名(先着)

みなさんにお会いできることを楽しみにしています!

(後半)OSCON 2013(Open Source Convention)行ってきた

$
0
0

こんにちわ。
今回は前回に引き続きOSCON基調講演と気になるセッションの紹介をしたいと思います。
OSCONについては前回の記事を参考してくださいね。
※この記事については参加メンバーのヒアリングをもとに渡辺雄作(@waysaku)のほうで取りまとめております。

まずはこちら。

Facebookのインフラ責任者Jay Parikhの講演ではThe Open Compute Projectについての目的と概要、Facebookとしての取り組みを説明していました。
特にFacebook上で扱う2500億の画像の取り扱い(一日で3.5億の画像が投稿される!)は独自のデータセンターとラック、サーバを設計してコストを大幅に下げているとのこと。

OSCON 2013: Jay Parikh, "The Open Compute Project"





O’Reilly Mediaのfounder兼CEOのTim O’ReillyがCode for Americaについて説明していました。
この取り組みは政府と市民をOpen Sourceを使って繋いでいくという活動で、followshipと言われるグループごとにそれぞれが政府と市民のあり方を改善していこうというものです。
市民は技術を使って政府との関係を改善し、コミュニティを通じて参加者自身もスキルアップしていくということです。
Open Source(とコミュニティ)の考え方を社会に適用して、より良い社会にしていくという大きな潮流を感じました。

Code Is Making Government More Effective


GitHubのCEOであるTom Preston-Wernerのセッション。

信条にそって自由に仕事をすることが人々を幸せにすると考えていて、
GitHubも自由を信条にしているがそのためにはライセンスの管理が重要であるとのこと。
ソースコードが自由になるためにライセンスの管理は非常に重要であると言っていました。(そのためにGitHubには簡単にライセンスを選択できる機能があるとのこと)
ライセンスが設定されていないソースコードは、その意図が不明なためユーザーは使いたくても使えない場合があるので、今すぐライセンスを設定しようということでした。



個人的には基調講演で一番インパクトがあったLeigh Heymanのセッションです。
Open Government、Open Dataを掲げ政府がオープンソースを使った活動を説明していました。
https://petitions.whitehouse.gov/developers のサイトにもある通りいくつかの取り組みを既に行なっているようです。

試しに api.whitehouse.gov/v1/petitions.json?limit=3&offset=0 に対してGETリクエストを発行してみたところ、JSON形式でホワイトハウスへの請願書のリストが取得できました。(一部長い文字列は省略しています)
{
    metadata: {
        responseInfo: {
            status: 200 (number)
            ,developerMessage: OK (string)
        }
        ,resultset: {
            count: 2121 (number)
            ,offset: 0 (number)
            ,limit: 1 (number)
        }
        ,executionTime: 1376528388.07 (number)
    }
    ,results: [
        {
            id: 520bae1aadfd955536000004 (string)
            ,type: petition (string)
            ,title: "fugafuga" ,body: "hogehoge"
            ,issues: [
                {
                    id: 97 (string)
                    ,name: Job Creation (string)
                }
                ,{
                    id: 103 (string)
                    ,name: Labor (string)
                }
                ,{
                    id: 169 (string)
                    ,name: Transportation and Infrastructure (string)
                }
            ]
            ,signatureThreshold: 100000 (number)
            ,signatureCount: 387 (number)
            ,signaturesNeeded: 99613 (number)
            ,url: https://petitions.whitehouse.gov/fuga
            ,deadline: 1379089178 (number)
            ,status: open (string)
            ,response: null (object)
            ,created: 1376497178 (number)
        }
    ]
}
さらに api.whitehouse.gov/v1/petitions/[id].json のようにidに対してGETリクエストを発行すると請願書の詳細とその請願書に署名した人のリストも取得できます。
リアルタイムにこだわらないならダンプデータのダウンロードも可能のようです。
APIドキュメントはGitHubで管理されプルリクエストも受け付けているようです。
/Developers
We the People API



ここからは参加メンバーの気になるセッションを紹介したいと思います。

@fuzzy31u(国境を超えるエンジニア)のピックアップ
安全で継続的な開発を行う上での心得、環境について。目新しいことを言っているわけではないのですが、Mozilla社での開発の様子を聞いて改めて意識すべき心得が多々ありました。最後の "The only way to get good at deployment is to deploy a lot."(良いデプロイを行う唯一の方法は、デプロイをたくさんすることである)の名言?がかっこよかったです。


Server-Side Push: Comet, Web Sockets, and Server-Sent Events come of age
純粋なHTTP通信のみで事足りていた時代から、現代のリアルタイム通信を必要とするアプリケーションやニーズが増えた歴史的背景。
それに伴うプロトコルの多様化、現在最もポピュラーなWebSocketの解説、デモ。皮肉やジョークを交えたユーモラスなセッションでした。


 
    Java EE7でサポートされたWebSocketをJavaで実装する方法について。Getting Startedなので実装方法の紹介がメインでした。WebSocketといえばNode.jsで実装される例が多かったですがJavaがメインの我々としては選択肢が広がったといえるのではないでしょうか。

Scaling systems configuration at Facebook: the paradigms, design, and software behind managing massive numbers of systems with open source and small teams
    FacebookのConfiguration Managementという職種の方のセッション。Facebookの数万ものシステムのConfigurationをたった4人で管理しているそうです。スケールすること、手軽にConfigに手を加えられることなどを重視しているそうです。残念ながら英語が早すぎて理解がおろそかですが。ツールの一例が紹介されていました。


@horimislime(にわかpythonista)のピックアップ


OpsCode CTOによるChefのチュートリアル。レシピの書き方からResourceやAttributeといったChefの機能説明、さらにknifeやohai, chef-zeroといったツールの使い方まで網羅されています。かなり広くカバーされているので、Chefの基本部分は分かったけど、この部分はどう書くのが良いんだろう・・?といった痒いところに手の届く情報が見つかるかもしれません。

これ以外でも最近話題のDockerやAnsible、Puppetなどの発表が勢ぞろいで、DevOpsの盛り上がりを感じさせられました。
Why docker | OSCON 2013
PUP201: How To Use Puppet Like An Adult // Speaker Deck


そしてOSCONはソフトウェアに限定した発表ばかりではありません。ArduinoやRaspberryPiのようなハードウェアを駆使した内容のものも幾つかあり、中でも印象に残ったのはこちらの自作キーボードに関する発表。

キーボードの自作に必要な工具や部品などの解説から、実際に発表者が作成したプロトタイプも発表中に触らせてもらいました。


エンジニアにとってはここまで完全にカスタマイズできるのは理想的ですね。かなりハードルは高いですが・・wまだこれだ!というようなキーボードに出会えてない人は試してみたらどうでしょう:)


@koko1000ban(社内Ruby布教活動家)のピックアップ
dl.google.com: powered by Go
HackerNewsをはじめ各所で話題になったセッション  
ありがちなメンテされなくなったレガシーコードの置き換えの話です。

スライド中のレガシーコード要約に
"incomplete docs, tests", "copy/paste code", "... different languages"
ということが書いてあり、Googleでもそれが起きるのかと驚いてしまいました。

GoogleではC++11がすでに使われてるみたいですが

それでもわざわざC++で書き直す理由が見つからないと言っていることやmemcachedをgroupcacheというライブラリでキャッシュプールを構成するやり方に変えたことなど色々興味深く、後ほどコードベースで詳しく追って行きたいと思います。

余談ですが、C++の代替としては個人的にはRustをおっかけていて、OSCONでもいくつかセッションあったのでそちらも追記しておきます。



@waysaku(どやり開発プロセスエンジニア)

OSCONは開発者のお祭りのような印象を受けました。様々な日本のカンファレンスと違い、老若男女幅広い層の参加者がいたように感じました。
その中で私が印象的だったのは基調講演初日のClojureを使ってRoombaやAR Droneを楽しそうに操る女性のセッションです。


熱中していることを楽しそうに発表しているのを見ると、こっちまでワクワクしますね。



-まとめ-
サイバーエージェントでは海外カンファレンスへの参加も増えてきており、今後も世界中の最新の技術をキャッチアップし発信していこうと思っています。
年内にはVelocity 2013 in NYCやQCon San Francisco 2013もありますし、またこのブログで現地レポートなどお届けできると思いますのでお楽しみに!

Javaではじめるakka入門

$
0
0

はじめまして。
ブロググループ所属の見原と申します。
今回は先日担当した案件で利用した、akkaを紹介させていただきます。

はじめに

akkaはtypesafeが提供する、イベント駆動の分散並列型アプリケーションフレームワークです。
並列処理が簡単に記述出来るほか、複数のマシンを用いた分散処理の実現、
「let it crash」という設計思想に基づいたロジックとリカバリ処理の分離などが特徴です。
akkaのサンプルはscalaが多いのですが、今回はjavaで説明していきます。

まずはMavenを利用したアプリケーションを作成します。
akkaを利用するため、以下をpom.xmlに記載します。
<repositories>
    <repository>
        <id>typesafe</id>
        <name>Typesafe Repository</name>
        <url>http://repo.typesafe.com/typesafe/releases/</url>
    </repository>
</repositories>
<properties>
    <com.typesafe.akka.version>2.1.4</com.typesafe.akka.version>
</properties>   

<dependency>
    <groupId>com.typesafe.akka</groupId>
    <artifactId>akka-actor_2.10</artifactId>
    <version>${com.typesafe.akka.version}</version>
</dependency>
<dependency>
    <groupId>com.typesafe.akka</groupId>
    <artifactId>akka-remote_2.10</artifactId>
    <version>${com.typesafe.akka.version}</version>
</dependency>
<dependency>
    <groupId>com.typesafe.akka</groupId>
    <artifactId>akka-kernel_2.10</artifactId>
    <version>${com.typesafe.akka.version}</version>
</dependency>

メッセージの送信

まずは一番基本的なメッセージの送信を試してみます。

public class SimpleActorSystem {

    public static void main(String[] args) {
        ActorSystem system = ActorSystem.create("system");
        ActorRef ref = system.actorOf(new Props(SimpleActor.class), "simpleActor");

        String message = "hello.";
        ref.tell(message, null);

        try {
            Thread.sleep(3000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        system.shutdown();

        System.out.println("end.");
    }
}

4行目で生成しているActorSystemはakkaにおいて中核となるクラスです。
次の行では、これを用いて実際にメッセージの処理をするActorを生成しています。
メッセージの送信にはtellメソッドを利用します。
第一引数には送信したいメッセージを、第二引数には送信元とするActorを指定します。
今回は送信先で特に送信元に対して処理を行わないのでnullを指定しています。

次に、メッセージを受け取るActorを実装します。

public class SimpleActor extends UntypedActor {

    @Override
    public void onReceive(Object message) throws Exception {
        if (message instanceof String) {
            System.out.println("message:" + message);
        } else {
            System.out.println("unhandled message.");

            // 想定しない型のメッセージはスルーする
            unhandled(message);
        }
    }

    @Override
    public void preStart() {
        System.out.println("preStart");
    }

    @Override
    public void postStop() {
        System.out.println("postStop");
    }

}

Actorは基本的にUntypedActorを継承します。
onReceiveメソッドが送信されたメッセージを処理するメソッドになります。
今回はStringのメッセージを出力、それ以外のメッセージはスルーするつくりになっています。
preStartはActorのスタート時に、postStopはActorの停止時に実行されるので、
何らかの処理をしたいときに任意にOverrideします。

これで実行の準備が整いました。
SimpleActorSystemを実行してみると、以下のような結果が得られます。
preStart
message:hello.
end.
postStop

メッセージの送受信

次に、メッセージを送ってActorの返事を待ってみます。
先ほどtellしていた部分を以下のように書き換えます。
private Integer result = 0;
try {
    // メッセージを送信し、結果を受け取る
    result = (Integer) Await.result(Patterns.ask(actor, message, 5000), Duration.create(5000, TimeUnit.MILLISECONDS));
} catch (Exception e) {
    e.printStackTrace();
}
System.out.println("result=" + result);

try {
    result = (Integer) Await.result(Patterns.ask(actor, message, 5000), Duration.create(5000, TimeUnit.MILLISECONDS));
} catch (Exception e) {
    e.printStackTrace();
}
System.out.println("result=" + result);

try {
    // 想定しない型を送信する。Exceptionが発生する
    result = (Integer) Await.result(Patterns.ask(actor, 1, 5000), Duration.create(5000, TimeUnit.MILLISECONDS));
} catch (Exception e) {
    e.printStackTrace();
}
System.out.println("result=" + result);
メッセージの送信にはtellを使用していましたが、代わりにPatternsのaskメソッドを利用します。
こちらを用いると結果がFutureで返ってくるので、Awaitのresultメソッドを用いてその結果の待機、取得を行います。


次に、Actorの中身を以下のように書き換えます。
int state = 0;

@Override
public void onReceive(Object message) throws Exception {
    if (message instanceof String) {
        System.out.println("message:" + message);
        sender().tell(++state, self());
    } else {
        System.out.println("unhandled message.");
        unhandled(message);
    }
}
先ほどの例では意図するメッセージを受け取ったとき、それを出力するだけでした。
しかし、今回は送信元に対してメッセージを送り返しています。

こちらを実行すると以下のような結果になります。
preStart
message:hello.
result=1
message:hello.
result=2
unhandled message.
result=2
java.util.concurrent.TimeoutException: Futures timed out after [5000 milliseconds]
    at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:96)
    at scala.concurrent.impl.Promise$DefaultPromise.result(Promise.scala:100)
    at scala.concurrent.Await$$anonfun$result$1.apply(package.scala:107)
    at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:53)
    at scala.concurrent.Await$.result(package.scala:107)
    at scala.concurrent.Await.result(package.scala)
    at jp.ameba.blog.akka.sample.ask.AskActorSystem.main(AskActorSystem.java:43)
end.
postStop
2回目の送信までは正常に動作しています。
しかし、3回目の送信ではActorが意図しない型を送信しているため、
Actorが送信元にメッセージを送り返してくれず、タイムアウトが発生しています。

複数サーバを用いた分散処理

先頭でもお話しした通り、akkaを用いると、複数のマシンを用いた分散処理の実現が容易に可能です。
最後に、こちらの実装をご紹介したいと思います。

今回はローカル実行用とリモート実行用にActorSystemを二つ用意します。
まずはリモート実行用のクラスを作成します。
public class RemoteSystem implements Bootable {
    final ActorSystem system = ActorSystem.create("remoteSys", ConfigFactory.load().getConfig("remoteSetting"));

    @Override
    public void startup() {
        System.out.println("start");
    }
   
    @Override
    public void shutdown() {
        system.shutdown();
    }
}

簡単ですね!
これまでと異なるのは、Bootableインターフェースを実装していることです。
startupメソッドとshutdownメソッドを実装してあげる必要があります。
さらにもう一点異なるのは、ActorSystemの生成の際、設定をファイルから読み込んでいることです。
設定ファイルから「remoteSetting」という設定を探して読み込んでいます。

設定ファイルは「application.conf」という名前で以下のように記述します。
localSetting {
    include "common"
    akka {
        remote {
            transport = "akka.remote.netty.NettyRemoteTransport"
            netty {
                hostname = "127.0.0.1"
                port = 2552
            }
        }
    }
}

remoteSetting {
    include "common"
    akka {
        remote {
            transport = "akka.remote.netty.NettyRemoteTransport"
            netty {
                hostname = "127.0.0.1"
                port = 2553
            }
        }
    }
}
ローカルで実行するための設定と、先ほど読み込んだリモート用の設定を記述してあります。
実際に複数サーバで実行したいのですが、今回はテストのために同じIP、異なるポートを指定してひとつのマシンで実行出来るようにしています。

また、includeという記述がありますが、これはほかのファイルに記述したものを読み込むものです。
今回、「common」をincludeするという記述になっているので、
「common.conf」という名称のファイルを探して読み込みます。
common.confの内容は以下のようになっています。
akka {
    actor {
        provider = "akka.remote.RemoteActorRefProvider"
    }
}
次にローカル用のクラスを生成します。
public class LocalSystem implements Bootable {

    final ActorSystem system = ActorSystem.create("localSys", ConfigFactory
            .load().getConfig("localSetting"));

    private static final String AKKA_PROTOCOL = "akka";
    private static final String REMOTE_SYSTEM_NAME = "remoteSys";
    private static final String REMOTE_HOST_IP = "127.0.0.1";
    private static final int REMOTE_HOST_PORT = 2553;

    @Override
    public void startup() {
        String message = "hello.";

        // ローカルのActorを生成
        System.out.println("local actor test.");
        ActorRef localActor = system.actorOf(new Props(RemoteActor.class),
                "localActor");
        localActor.tell(message, null);

        try {
            Thread.sleep(2000L);
        } catch (InterruptedException e) {
        }
        System.out.println("-----");

        // リモートのActorを生成
        System.out.println("remote actor test.");
        ActorRef remoteActor = system.actorOf(new Props(RemoteActor.class)
        .withDeploy(new Deploy(new RemoteScope(new Address(
                AKKA_PROTOCOL, REMOTE_SYSTEM_NAME, REMOTE_HOST_IP,
                REMOTE_HOST_PORT)))), "remoteActor");
        remoteActor.tell(message, null);

        try {
            Thread.sleep(2000L);
        } catch (InterruptedException e) {
        }
        System.out.println("-----");

        // ラウンドロビンでActorにメッセージを送信
        System.out.println("router test with RoundRobinRouter.");
        List<ActorRef> actors = new ArrayList<>();
        actors.add(remoteActor);
        actors.add(localActor);
        ActorRef roundRobinRouter = system.actorOf(new Props(RemoteActor.class)
        .withRouter(RoundRobinRouter.create(actors)));
        for (int i = 0; i < 6; i++) {
            String roundRobinMessage = message + i;
            roundRobinRouter.tell(roundRobinMessage, null);
        }

        try {
            Thread.sleep(2000L);
        } catch (InterruptedException e) {
        }
        System.out.println("-----");

        system.shutdown();

        System.out.println("end.");
    }
}
ローカル用のActorの生成はこれまでと一緒です。
リモート用のActorはDeployというクラスを用いて生成しています。
純粋にメッセージを送るだけなら、生成したActorに対してtellを実行するだけで可能です。
しかし、実際に利用する場合、特定のサーバに存在するActorに対してメッセージを送信するのではなく、
複数サーバに存在するActorに対して平等にメッセージを送信することで、負荷の分散を図りたいものです。

そこで便利なのがRouterです。
今回はRoundRobinRouterを利用しています。
このルーターに対してメッセージの送信を行うと、このルーターが管理しているActorに対して、
名前の通りラウンドロビンでメッセージの送信を行ってくれます。
このほかにも、ランダムでメッセージの送信を行うRandomRouterや、
全Actorに一括送信を行うBroadcastRouterなどが存在します。

では、実際に今記述したものをテストしてみます。
Bootstrapインターフェースを実装したクラスは、akkaの提供するスクリプトで実行することができます。

http://typesafe.com/platform/runtime/akka/download
こちらより、最新のakkaをダウンロードして解凍します。

作成したものをjarにして、deployディレクトリに配置すれば準備完了です。
linuxならbinディレクトリにあるakka、Windowsならakka.batに対して実行したいBootableを実装したクラスを完全限定名で指定すれば、プロセスが起動します。

まず、リモート用のActorSystemを起動してみます。
akka-2.1.4\bin>akka.bat jp.ameba.blog.akka.sample.remote.RemoteSystem
Starting Akka...
Running Akka 2.1.4
Deploying file:/akka-2.1.4/bin/../deploy/akka-s
ample-app.jar
[INFO] [07/08/2013 11:27:35.109] [main] [NettyRemoteTransport(akka://remoteSys@127.0.0.1:2553)] RemoteServerStarted@akka://remoteSys@127.0.0.1:2553
Starting up jp.ameba.blog.akka.sample.remote.RemoteSystem
start
Successfully started Akka
次に同じようにローカル用のActorSystemを起動し、メッセージを送信します。
ローカルの実行結果は以下の通りです。
akka-2.1.4\bin>akka.bat jp.ameba.blog.akka.sample.remote.LocalSystem
(略)
local actor test.
static initialization completed. hostName=pctest
message=hello., state=1, hostName=pctest
-----
remote actor test.
[INFO] [07/08/2013 11:35:37.186] [main] [NettyRemoteTransport(akka://localSys@127.0.0.1:2552)] RemoteClientStarted@akka://remoteSys@127.0.0.1:2553
-----
router test with RoundRobinRouter.
message=hello.1, state=2, hostName=pctest
message=hello.3, state=3, hostName=pctest
message=hello.5, state=4, hostName=pctest
-----
Successfully started Akka

Shutting down Akka...
Shutting down jp.ameba.blog.akka.sample.remote.LocalSystem
Successfully shut down Akka
次にリモートの実行結果は以下の通りです。
[INFO] [07/08/2013 11:35:37.232] [remoteSys-10] [NettyRemoteTransport(akka://remoteSys@127.0.0.1:2553)] RemoteClientStarted@akka://localSys@127.0.0.1:2552
static initialization completed. hostName=pctest
message=hello., state=1, hostName=pctest
message=hello.0, state=2, hostName=pctest
message=hello.2, state=3, hostName=pctest
message=hello.4, state=4, hostName=pctest
[INFO] [07/08/2013 11:35:45.333] [remoteSys-7] [NettyRemoteTransport(akka://remoteSys@127.0.0.1:2553)] RemoteClientShutdown@akka://localSys@127.0.0.1:2552
RoundRobinRouterに対して送信したメッセージがローカルとリモートのActorに対して均等に送信されていることが確認できます。

まとめ

今回はakkaの初歩の部分のみのご紹介になりましたが、
他にもDispatcherを用いると並列処理が容易に記述できたり、
SupervisorStrategyと用いるとロジックとリカバリ処理の分離が出来たりと、
様々な便利な機能を有しています。
また、まだテスト段階ではありますが、将来的にはクラスタリングもサポートされます。

この記事でご紹介したものと、SupervisorStrategyなどを含めたサンプルアプリは以下に公開しておりますので、
ご興味のある方はご覧ください。
https://github.com/tm8r/akka_sample_app

PR: 【三井の賃貸】最新値下げ物件が集結!賃料改定物件特集

$
0
0
<平日毎日更新>直近2週間以内に賃料が下がった物件情報をおすすめ順にご紹介!!

ピグ麻雀のアルゴリズム

$
0
0

皆様初めまして。 12年度新卒のぱっとしない方のハカマタです。 アメーバピグの制作部署で、サーバサイドエンジニアとして陰ながら頑張っています。

さて、突然の告白ですが最近私は仕事中にアメーバピグで麻雀をしています。 しかし私は今まで一度たりとも叱られたことがありません。 それは、私が叱責に耐えうるメンタルが無いと先輩方に諦められているからでしょうか? 違います、私は麻雀ゲームの制作者メンバーで、デバッグという名目で、ピグで麻雀をしているためです。 本日の記事は、ピグでリリースしたピグ麻雀についてお話します。

ピグ麻雀


ピグ麻雀はエンジニア・ディベロッパー・デザイナー各1名で制作したもので、 私はエンジニアとして参加しました。 サイバーエージェントのクリエイターブログに過去の記事として、デザイナーの鈴木さんの記事『ピグ麻雀におけるデザインのポイント』と、ディベロッパーの鈴木さんの記事『ピグ麻雀がリリースされるまで』がありますが、私はサーバサイドエンジニアとしてピグ麻雀のアルゴリズムについて簡単に説明します。 また、記事の最後に麻雀の開発にあたっての個人的な感想を述べます。


※この記事は皆様が麻雀のルールを認識していることを前提に書いておりますので、 もし麻雀のルールがわからない方は途中を飛ばして最後の私の開発を終えての感想のみお読みいただければ幸いです。

麻雀の役判定アルゴリズム

ピグ麻雀の役判定アルゴリズムについてお話しする前に、麻雀の役判定の流れを説明しておきます。 麻雀の役判定は、和了型手牌(※ 一般的な名称ではなく、独自につけた名称です)を用いて行います。 和了型手牌は、七対子と国士無双を除いて、雀頭と面子4つから構成されます。 この和了型手牌を手牌から網羅的にリストアップして、 リストアップされた各々の和了型手牌で役判定を行い、最良の役を持った和了型手牌から和了役を決定します。 このアルゴリズムを簡単にまとめると以下のようになります。 


これから上記の処理の詳細を 1.和了型手牌のリストアップ 2.役判定 に分けて説明していきます。 

1.和了手牌のリストアップ

ピグ麻雀では麻雀牌をenumで定義しており、各牌のコードを連番でつけています。

/**
 * 麻雀牌
 */
public enum MahjongTile implements Transferable {
	/** 萬子1 */
	M1(0, MahjongTileType.MANZU, 1),
	/** 萬子2 */
	M2(1, MahjongTileType.MANZU, 2),
	/** 萬子3 */
	M3(2, MahjongTileType.MANZU, 3),
	/** 萬子4 */
	M4(3, MahjongTileType.MANZU, 4),
	/** 萬子5 */
	M5(4, MahjongTileType.MANZU, 5),
	/** 萬子6 */
	M6(5, MahjongTileType.MANZU, 6),

    ・・・・

	/** 白 */
	HAK(31, MahjongTileType.SANGEN, 0),
	/** 發 */
	HAT(32, MahjongTileType.SANGEN, 0),
	/** 中 */
	CHN(33, MahjongTileType.SANGEN, 0), ;

	/** 牌コード */
	private int code;
	/** 牌種別 */
	MahjongTileType type;
	/** 牌数値(役牌は0) */
	private int number;

	private MahjongTile(int code, MahjongTileType type, int number) {
		this.code = code;
		this.type = type;
		this.number = number;
	}


プレイヤーは各牌の所有枚数を配列で保持しています。


private int[] tiles = { 1,0,0,0,0,0,0,0,1, // 萬子
1,0,0,0,0,0,0,0,1, // 索子
1,0,0,0,0,0,0,0,1, // 筒子
1,1,1,1, // 風牌
2,1,1}; // 三元牌  

和了型手牌はこの配列を用いて判定します。判定のフローを以下に示します。


この処理を行うことで、手牌を網羅的に取得することができます。刻子優先取得、順子優先取得というフェーズがある理由は、刻子や順子のいずれかのみを優先して取得してしまうと問題が生じるためです。 例えば 
222 333 444 という手牌があったとして、 これを順子優先で取得すると234 234 234という手牌になります。 例えば残りの手牌が②刻子と五雀頭でフーロが無い場合では、 役満の四暗刻になりますが、順子を優先して取得された場合には四暗刻の判定ができません。


 2.役判定 

和了型手牌の結果をもとに役判定を行います。 先ほどの和了型手牌の雀頭・面子以外に、 プレイヤーが副露しているか、プレイヤーの最後の和了牌等の情報をもとに役判定を行います。 ピグ麻雀の役判定はファサードパターンを用いて実装されています。 和了型手牌一覧を窓口である和了判定処理に渡すことで、それぞれの和了型手牌の和了役を全て取得するようにしています。 インターフェースで役判定を行うメソッドを定義して、その実装クラスでそれぞれの役判定を行っているため、役を追加する場合は新たに役判定のクラスを追加するだけです。


今回は役判定のうち、麻雀の基本役であるピンフの役判定について説明します。 ピンフであるか判定する場合には以下の手順で行います、副露してないか 雀頭が役牌であるか、雀頭が場風・自風であるか、和了牌が両面待ちであったか、面子の構成要素が順子のみであるかを調べ、これらの条件をクリアしたものがピンフになります。

(訂正) 雀頭が役牌であるか→雀頭が役牌でないか


最後に


ピグ麻雀の開発期間は3ヶ月でした。 私を含め、新卒3人のチーム全員が麻雀未経験者ということもあり、ルールを把握することからプロジェクトを始めなければなりませんでした。プロジェクト開始後、麻雀入門書を手にとってルールの難しさに心が折れたことを覚えています。弱音ばかりはいていても仕方ないので入門書片手に、会議室で麻雀をしたり、雀荘に行ったりして麻雀について学んでいました。麻雀好きの先輩方からすれば麻雀の実装は相当楽そうに映っていたかもしれませんが、実際は…(以下省略)。

また、この3ヶ月のうち、最も時間を割いたのはテストでした。 動作確認では確認しづらいテストはユニットテストで動作を担保しました。実際に200以上のテストケースを作成しました。加えて、クライアントサイドとの通信テストも行う必要があり、配牌チートコマンドを作ってあらゆる処理をテストしました。 例えば、国士無双聴牌の暗カンロンなどが行えるかといったものです。

念入りにテストしたつもりでも、リリース後にバグが発見されました。 バグの原因の多くは、ルールの認識不足によるものでした。当たり前のことですが、 麻雀をはじめとして、一般的に普及しているゲームのルールを把握することは、システムの仕様を把握することと同義であり、ルールを把握していない箇所はバグとなります。 また、ゲームにはローカルルールが存在し、ユーザ間でルールの認識が異なり、開発者とユーザとの間でルールの認識のギャップが発生してしまうため、ユーザはバグであると感じます。
このため、一般的に普及したゲームの開発を行う際は、ルールを完璧に把握し、提供するゲームのルールを、改めてユーザに明示する必要性を感じました。

今後もピグ麻雀の改善をしていきますので、
引き続きピグ麻雀を宜しくお願いします。

redisをsentinelとAliasIPを利用して冗長化

$
0
0

どうも初めまして2012年度入社の社内ニート予備軍editnukiです。
普段は引きこもって WebSocketで監視もリアルタイムに を書いた社内ニートさんの下でコミュニティサービスのインフラをやっております。
運用面以外ではrpmパッケージ作ったりしています。

さて、本題ですがコミュニティサービスでもredisを利用したいという声が最近多くなりいくつかのサービスではredisを導入しているのですがマスターとなるredisが死ぬと更新系が一切できなくなるため、マスターが死んだ時はアプリの向き先をスレーブに変更しなければなりません。
今までのredisの構成としては下図の様な構成でした。


redis構成図1

図1.今までの構成

redisの2.6系がリリースされた時に「sentinel」というフェイルオーバーの機能が追加されました。 詳細は公式ドキュメントをご参照ください。
フェイルオーバーしたとしてもアプリ側にマスターが切り替わったことを通知することはできないため、sentinelを導入しても同様の手運用の部分は変わりませんでした。
先日GMO MEDIAの宇津井さんがRedis Sentinelを運用してみたお話というブログを書かれていて、宇津井さんはiptablesを利用した手法を利用されています。
宇津井さんも書かれていますが、この時はフェイルバック機能を持っていなかったのです。先日RELEASE NOTESを読んでいて、ver2.6.13からフェイルバックできるようになりました。
[NEW] Sentinel: turn old master into a slave when it comes back.
というわけで、私が検証した方法の設定例を上げていきますです。
図1の構成にもう1台追加します。


redis構成図2

図2. sentinel用サーバ追加

redisサーバにsentinelを導入しても良いのですが、私は監視とサービスを分けたいのであえて別サーバにsentinelを切り分けてます。
この様に1台追加するだけでフェイルオーバーはできるのですが、このままではweb-serverからはマスターを直に見ていてフェイルオーバーした後もマスターに対して更新処理を行おうとします。
なので私はマスターに対してAliasIPを付与し、web-serverからはそのAliasIPへ更新処理を行うようにしました。 今回はこのAliasIPがキモになります。


redis構成図3

図3. マスターへAliasIP追加

この様にすればAliasIPの付け替えをするだけで更新処理の向き先を変更が可能になります。
そして、次は「じゃAliasIPの付け替えはどうやってやるの?」ということになると思うのですが、sentinelにはフェイルオーバー時にclient-reconfig-scriptを使って指定したスクリプトを実行させることができます。
私のsentinel.confの設定例になります。
PATHがおかしいのは私が自分でビルドしたrpmパッケージなので気にしないでください。
この辺は適当に合わせてもらえればいいと思います。

port 26379
daemonize yes


loglevel notice
logfile /usr/local/redis/logs/sentinel.log
pidfile /usr/local/redis/logs/sentinel.pid


sentinel monitor ca-redis-sentinel redis-sentinel01 6379 1
sentinel down-after-milliseconds ca-redis-sentinel 10000
sentinel failover-timeout ca-redis-sentinel 900000
sentinel can-failover ca-redis-sentinel yes
sentinel parallel-syncs ca-redis-sentinel 2
sentinel client-reconfig-script ca-redis-sentinel /usr/local/redis/bin/alias_ip_change.sh


ポイントだけ説明しておくと
sentinel monitor ca-redis-sentinel redis-sentinel01 6379 1

「ca-redis-sentinel 」というのはただの監視グループの名前です。「redis-sentinel01」のところは実IPでも可能です、私は/etc/hostsに全部指定しているのでホスト名で書いてしまってます。
最後の1というのは複数のsentinelサーバがいる時に何台以上のsentinelがマスターダウンを検知したらフェイルオーバーをするものかです。
今回はsentinelは1台なのでここは必ず1になります。2にするとフェイルオーバーしないのでご注意を。

sentinel parallel-syncs ca-redis-sentinel 2

スレーブを追加する時はこの2という数字をスレーブの台数の数字に変更してsentinelの再起動をしてください。

sentinel client-reconfig-script ca-redis-sentinel /usr/local/redis/bin/alias_ip_change.sh

フェイルオーバー時のスクリプトですが、やっつけ&力技で書いてしまったので汚いのですが下記の通りとなっています。 AliasIPなどは各環境に合わせて記述してくださいませ。

#!/bin/bash


LOG="/usr/local/redis/logs/sentinel.log"
IP="/sbin/ip"
ETH_DEVICE="eth0"
ALIAS_DEVICE="eth0:0"
ALIAS_IP="エイリアスIP"
PREFIX="プレフィックス"
NETMASK="ネットマスク"
BROADCAST="ブロードキャスト"
REDIS_CLI="/usr/local/redis/bin/redis-cli"
SENTINEL_PORT="26379"
REDIS_COMMAND="info"
GREP="/bin/grep"
CUT="/bin/cut"
SSH_USER="sshできる適当なユーザ名"


# 旧マスターからAliasIPを取り除くssh $SSH_USER@$ALIAS_IP -o "StrictHostKeyChecking no" "sudo $IP addr delete $ALIAS_IP/$PREFIX broadcast $BROADCAST dev $ETH_DEVICE label $ALIAS_DEVICE"
echo "DELETE $ALIAS_IP from Master server" >> $LOG


# 新マスターにAliasIPを付与する
MASTER_IP_CHECK=`$REDIS_CLI -p $SENTINEL_PORT $REDIS_COMMAND | $GREP master0 | $CUT -d '=' -f 4 | $CUT -d ':' -f 1`
ssh $SSH_USER@$MASTER_IP_CHECK "sudo $IP addr add $ALIAS_IP/$PREFIX broadcast $BROADCAST dev $ETH_DEVICE label $ALIAS_DEVICE"
echo "ADD $ALIAS_IP to new Master servre" >> $LOG

exit 0;

(※我ながらひどいスクリプトだと思うので、いつか綺麗にしておきます・・・)

AliasIPを取り除く時にサーバのIPではなくAliasIPへsshをしており、AliasIPの付いてるサーバが変わるとknown_hostsで怒られてスクリプトがうまく動かなくなるので、「-o "StrictHostKeyChecking no"」オプションを利用しています。そうするとサーバが変わっていてもknown_hostsを勝手に書き換えてくれます。 このスクリプトはredisサーバのIPを記述していないのでサーバが増えても変更する必要がないです。
あとは、このスクリプトに実行権限は付けておきましょう。
 # chmod a+x /usr/local/redis/bin/alias_ip_change.sh

検証方法
フェイルオーバーの検証としてサーバごとshutdownしてみる、redisのプロセスを起動スクリプトで落とすの2パターンをやってみました。 更新処理はsentinel用のサーバからAliasIPにsetを大量に発行するものをbashで書いて実行しました。

結果
マスター昇格するスレーブサーバでの処理
$ /usr/local/redis/bin/redis-cli monitor
~一部抜粋~
1373885267.764209 [0 sentinelサーバIP:50811] "SLAVEOF" "NO" "ONE"
1373885268.267852 [0 sentinelサーバIP:50811] "INFO"
1373885268.468494 [0 sentinelサーバIP:62899] "SUBSCRIBE" "__sentinel__:hello"
1373885268.468538 [0 sentinelサーバIP:62898] "INFO"
マスター昇格するredisではSLAVEOF NO ONEを実行してマスターに昇格させていることがわかります 更新処理ですが、既存のコネクションは旧マスターとのコネクションなのでタイムアウトします。 新規でコネクションを張った場合は20秒程度で更新処理を再開することができました。 アプリ側でredisへのタイムアウトを20~30秒にしておけばよいと思います。 タイムアウトしたら再度setする処理とか入れておくと更によいかと。

注意点
この手法を利用する時の注意点をいくつかあげておきます。

1. client-reconfig-scriptの設定をするsentinelは1つに
 sentinelプロセスは1つでなくても良いが複数プロセス(サーバ)で起動した時にclient-reconfig-scriptを記述すると全部のsentinelでスクリプトを実行してしまいます(私が検証したら全部のsentinelで実行しようとしてました)

2. スレーブ用のredisは自動起動offにしておきましょう。
 スレーブの参照用VIPを立てた場合、redisが落ちたりサーバの再起動が起きるとマスターとレプリを張らずに独立したredisとして立ち上がるのでデータの不整合が起きている。  VIPを立てた場合はLBから切り離して手動で起動・slaveofを実行する必要がある

3. スレーブの台数を増やしすぎない
 redisは0からデータを取りに行くのでフェイルオーバーが起きると新マスターから全台データを取得しに行くので大量のトラフィックが発生する。

4. redis.confにレプリの設定を記述しない
 slaveofコマンドは初期構築時に手動で実行し、confには記述しないでください。フェイルオーバーが起きてredisが再起動した時にconfに記述されてるサーバへslaveofコマンドを実行して構成が謎になります。レプリを張るのは初期構築時に全て手動で実行してください。

これで私は夜中にredisが
_人人 人人_ 
> 突然の死 <
   ̄Y^Y^Y^Y ̄
になっても対応しなくて済むようになると思いますワーイヽ(゚∀゚)メ(゚∀゚)メ(゚∀゚)ノワーイ
翌日対応で十分( ー`дー´)キリッ
maxmemoryの設定(実メモリの半分)忘れんなよ ウワァァァァァァヽ(`Д´)ノァァァァァァン!
全部のキーにexpireかけない運用とかやめてね(´;ω;`)ブワッ
    ,-∧,,∧-- 、 
   / (-ω-` ) / 
   r-くっ⌒cソ、 /   ん、障害? 大丈夫起きてるよ。 
  ノ '、 , 、 _, ' / /    ちょっと横になるだけ。 
.(_,.       ././   ちょっと長い瞬きするだけ…
,(.,_ `'ー-、_,,..ノ/ 
  ~`''ー--‐' 
ばいちっ。
Viewing all 161 articles
Browse latest View live