VOYAGE GROUP エンジニアブログ

voyagegroup_techのブログ
VOYAGE GROUPエンジニアブログです。

2013年11月

100万人が使うWebサービスを創造せよ!!大規模サービス構築プログラム「Sunrise2013」


こんにちは。システム本部 三浦@hironomiuです。

今年も11/9,10,11/16,17でVOYAGE GROUPの冬のエンジニアインターンSunrise2013が行われました。

本エントリーは週末4日間と言う短い期間で全力で学びそして全力でアウトプットしたSunriseの様子をお伝えしたいと思います。

なお、VOYAGE GROUPではエンジニア職の新卒採用を行っております。
本エントリーを見てVOYAGE GROUPのエンジニア職に興味を持って頂けましたら、「古より伝わりし大陸の秘宝」という面白いグループワークも行っておりますので、ぜひご応募ください!!
また、通年で募集している就業型実践インターンGuildもありますので、そちらへのご応募もお待ちしています!!

Sunrise生集合写真
PB100445

Sunriseは「100万人が使うWebサービスを創造せよ」を趣旨に学ぶインターンです。
そのため個々の細かい技術に対してはあまり深掘りせずサービスを構築、運営していく上で
強く必要となるであろう勘所や考え方を中心に講義は進みます。講義は座学、ワークショップの両方を行います。
又、全てチーム単位で章毎に学んだ事や疑問に思ったことを発表する形で進みます。

スケジュール
月日(曜日) 講義
11/9(土) ネットワーク
サーバヘルスチェック
事例紹介(広告配信システム)
11/10(日) データベースサーバ(運用、拡張戦略)
11/11-15 中間課題
11/16(土) 最終課題
11/17(日) 最終課題、発表

初日(11/9)
ネットワーク構成
(総評解説 小賀さん@makoga)
Webサービスはインターネット上で展開されるものであるためネットワークに対する知識は必須と言う観点から事前課題でネットワークに対する調査課題が出されます。その課題についてチーム毎に発表を行いました。

発表を行う一枚
sunrise04

サーバヘルスチェック(講師 三浦@hironomiu)
サーバの稼働状況を把握し将来予測を行うことはサービスを拡張する上で重要だと言う観点から
実際のサーバに対して負荷を掛けサーバの稼働状況を様々な観点(コマンド)から計測し考察を行いました。
講義は4章構成で各章毎にチーム単位で考察について発表を行いました。

チームでサーバに負荷を掛け稼働状況から考察を行う一枚
sunrise03

広告配信システム事例紹介(講師 大谷さん@katzchang)
弊社スーパーエンジニア 大谷さん@katzchangより広告配信システムZucks AdNetwork(開発プロジェクト名Zgok)の紹介を行いました。
広告配信システムの説明をしながらZucks AdNetworkを構築していく上で気にかけた事などを織り交ぜた事例紹介でした。

講義中の一枚
sunrise06

番外編 カレー料理対決(運営 人事 長ちゃん)
Sunriseはただ全力で学ぶインターンではありません!!
VOYAGE GROUPは仲間と事を成すと言うCREEDがあります。
裏ミッションでは仲間と事を成す楽しさを学ぶべく2チームに分かれ美味しいカレーを作る勝負を行いました。
そしてCTO小賀さん@makoga、総合プロデューサー佐々木Hさん、スーパーエンジニア 大谷さん@katzchang の豪華3名が各チームの料理に対してジャッジを行います。

料理風景
sunrise08

ジャッジ中の一枚
sunrise07


二日目(11/10)データベースサーバ運用、拡張戦略(講師 三浦@hironomiu)
大規模Webサービスを運営していく上でデータベースサーバは必ず肝になると言う観点から
データベースサーバの運用の勘所(SPOFの対策、I/O戦略、バックアップリストア、拡張戦略)やVOYAGE GROUPのデータベース事例を座学で行いました。
6章構成で進み各章毎にチームで学び取ったことや疑問点を発表する形で進みました。

座学中の一枚
sunrise05

中間課題
初日のサーバヘルスチェックの講義で用いたサーバ環境を使って平均レスポンスタイムによるパフォーマンスチューニングコンテストを行いました。
上位5位が0.01秒単位での団子状態となる熾烈な争いとなりました。
課題を出した側としても僅差の接戦は嬉しい結果でした。

三日目(11/16)最終課題
最終課題は4チームに分かれ各チームに一人社員がサポータとしてついて課題制作を行います。

チーム GiantMAK(かずき、まさや、あんなたん、ぶーちゃん、サポータ 三浦@hironomiu)
チーム Great Shining Dragon だっち(だっち、りゅう、こうき、サポータ ゆうくん)
チーム Ogyaaaaaaaaaaa!! (もぐ、West、わっさん、サポータ のっかさん)
チーム らすと(おだし、そうくん、琉玖、あきら、サポータ こてつさん)

CTO小賀さん@makogaより最終課題のお題が発表されます。初日、二日目、中間課題で学んだ内容を用いて提示したお題に対するサービス設計を行います。
今年のお題はSNSサービスでした。そこからサービス概要と共にサービスのアクティブユーザ数(月あたり、日あたり)、
アクセス傾向(書き込み、読み込み)など提示された各種数値を元に
必要となるプロダクト、サーバ台数、ネットワーク構成、月間辺りの費用、データフロー、プラスアルファで
独自のアイディアを盛り込み四日目14:30までにアウトプットし15:00から各チームプレゼン発表することが最終課題となります。
又、費用の算出やH/Wの選定を行う際に同じ目線にするため「さくらクラウド」にて実装する縛りを設けました。

アウトプット風景

sunrise13sunrise14


四日目(11/17)
最終課題制作、発表

前日から引き続き夜通しで各チームは最終課題のサービス設計を行いました。
各チームさくらクラウドの環境を用いて実機テストによりサーバ台数や費用の算出
実際のサービスのイメージをメンバー間で目線を合わせながらアウトプットしていました。

プレゼン風景
sunrise16sunrise15
sunrise17sunrise18
sunrise19sunrise20

GiantMAK資料抜粋
sunrise09

Great Shining Dragon だっち資料抜粋
sunrise12

Ogyaaaaaaaaaaa!!資料抜粋
sunrise11

らすと資料抜粋
sunrise10

各チームとも特色があり素晴らしい資料とプレゼンになりました。
Sunriseではプレゼン後に順位発表が行われます。短期間でのアウトプットでしたが
各チームのレベルが高く審査は凄く難航しました。

まとめ

初日から最終日まであっという間のインターンでした。
短期間でしたがSunrise生、サポータ含め深く打ち解け全てのメンバーが最終発表に向けてぶれずに進んだ結果ハイレベルな成果につながったと思います。
ここで得た仲間や経験を通じて、これからも「未知」なるサービスを「創造」し続け、価値のある素晴らしいモノ創りに挑戦し続けて欲しいです。

SPDYでWebサイト高速化ができるか試してみる

こんにちは。VOYAGE GROUPの駒崎です。

ECナビECナビ のエンジニアをやっています。つい先日入社しました。


この間(4ヶ月遅れですが)「WEB+DB PRESS Vol.75」にSPDYの記事が掲載されていたので、
現状、体感速度にどの程度効果が出るのか検証してみました。

SPDYって?という方は、
wikipedia さんに詳しく記載されていますので興味がある方はご参照ください。

試してみること

HTTPサーバ、HTTPSサーバ、HTTPSサーバ(SPDY) 
それぞれのサーバに画像コンテンツが大量にあるページを用意し、
各ブラウザでアクセスした平均ロード時間を比べてみます。
SSL証明書がオレオレ証明書のため、ブラウザでの計測は手動です。(´・ω・`)

サーバ
- CentOS 6.4(国内VPS)
- nginx 1.5.6 --with-http_spdy_module (SPDY/2)

使用ツール
- Chrome 31
- Firefox 25
- Safari 6
- Spdycat(Spdylay同梱のCUIツール)

まず準備

nginxをサクッとインストールして、
HTTP、HTTPS、HTTPS(SPDY)サーバをそれぞれ違うポートで立ち上げます。
ドキュメントルートは同じディレクトリを指すようにします。

SPDYを有効にするためには、nginx.conf で listenディレクティブにssl spdy を設定します。
こんな感じ。
    server {
        listen       9999 ssl spdy;

次にSpdycatを使って、nginxがSPDY対応出来たか確認します。
Macなら brew install spdylay で簡単にインストール出来ます。

普通のWebサーバ
% spdycat -v3 https://ほげほげ:9999/
[  0.051] NPN select next protocol: the remote server offers:
          * http/1.1
          NPN selected the protocol: spdy/3
SPDY対応サーバ
% spdycat -v3 https://ほげほげ:9998/
[  0.048] NPN select next protocol: the remote server offers:
          * spdy/2
          * http/1.1
          NPN selected the protocol: spdy/3

spdy/2が利用可能になってますね。

検証用Webページとして、
ドキュメントルートにmod_spdyデモサイトから拝借した画像196を含むページを設置します。
今のデモサイトには画像が50個しかないのですが、データは196個残っているのでそれもお借りしました。

いよいよ実験です。

測定結果

Chrome Firefox Safari
HTTP 1.140 2.234 2.928
HTTPS 1.372 6.312 2.618
SPDY 0.4896 7.492 2.908
それぞれ5回の平均ロード時間(sec)です。

評価

傾向がブラウザごとに大きく違ってしまい、
サーバ側の評価はしづらい結果となってしまいましたので、
ブラウザごとの評価をしてみます。

Chrome

SPDY自体、Googleで開発したプロトコルだけあり、
SPDY対応サーバではHTTP、HTTPSサーバと比べて倍近いロード速度になりました。
体感速度はだいぶ向上すると思います。

Firefox

Chromeが良いスコアの一方、
FirefoxはSPDY対応サーバに対してロード速度が悪化してしまいました。
Version11からSPDYに対応しているはずなのですが…。
5回しか試していないとはいえ、明らかな差が出ているように見えます。

ただ、Google画像検索(SPDY対応)で
network.http.spdy.enabled(.v2, .v3)のtrue/falseを切り替えて
それぞれロード時間を計測したところでは有意な差は見られませんでした。
ページ構成やサーバサイドの実装に依って差が出ているのかもしれません。

Safari

なぜかHTTPが遅い結果になっていますが、試行回数が少ないため誤差の範囲と考えました。
SafariはSPDY対応していないため、大きな違いはありませんでした。

その他

IEは計測出来ないのですが、IE10以前はSPDY未対応のため、
Safari同様の結果になるのでは?と予想しています。
Operaは時間の関係で調べませんでした。

おわり

上記の結果からは、
SPDY対応ブラウザでも体感速度に大きく違いがあることがわかりました。
Googleのサービスを使うならChromeを使うのが一番ですね。

SPDYを導入したからといって一概に速度向上に繋がるわけではないこともわかったので、
サーバ側に導入する際はターゲットやサイト構成をよく検討する必要がありそうです。 

また、SafariがSPDY対応した時は、
SPDYの最新バージョンでもう一度計測してみたいと思います。

参考サイト




プライベートメソッドのテストは必要ない!!

こんにちは、RPAの関口です。

最近週に一度、来年の新卒達と一緒にTDDをやりながらワイワイガヤガヤしております。そのなかで「プライベートメソッドのテストはどうすれば良いのか?」 という話題がありました。プライベートメソッドのテストについては
プライベートメソッドのユニットテストは書かないもの?
がよくまとまっていると思います。プライベートメソッドのテスト方法について考える中で「TDDの手順に従えばプライベートメソッドのテストがしたくなることは無い」のではないか?と思うようになりました。

プライベートメソッドはリファクタリングの結果現れる!

数値の配列を渡すと平均を計算して返してくれる機能を持ったクラス、AverageCalculatorを作りたいとします。平均計算の手順をまとめると以下のようになります。
  1. 配列の合計値を計算する
  2. 合計値を配列の要素数で割って返す
ここで「よし!まずは配列の合計値を計算する機能をつけよう!」と思って次のようなテストを書くと

calcSumメソッドの可視性について
  • 途中計算でしか使わない合計値の計算は、プライベートメソッドにしたい
  • でもプライベートメソッドだとテストのためにReflectionを使う必要があって面倒
という悩みが発生してしまいます。最初「平均値を返すメソッドを追加」しようと思っていたのに「合計値を返すメソッドを追加」しようとしたためです。平均値計算の手順はあくまで手順、初心に帰って平均値を返すテストを書きましょう。
そして合計値計算のメソッドは分離したいなぁと思ってリファクタリングする際に、calcSumという名のプライベートメソッドが自然と現れます。 このプライベートなcalcSumメソッドのためにテストを追加する必要はありません。中身がどのような実装になっていようと外部から呼び出されるcalcAverageメソッドが期待通りの結果を返してくれれば良いのです。またcalcSumメソッドはパブリックなcalcAverageメソッドを通じてテストされている、とも言えます。
 
パブリックメソッド経由でテストする
多くの場合、そのクラスのパブリックメソッド経由でプライベートメソッドのテストも同時に行えます。テストできているか不安があるならカバレッジを測定しましょう。

もしcalcSumの代わりに大変複雑な処理だった時はどうするの?

そのような場合、いきなりcalcAverage相当のメソッドを作るの事は難しいでしょう。一旦calcSumのメソッドの追加を行う必要が出てくるかと思います。もちろんテスト付きで。 でもそのcalcSumはAverageCalculatorクラスがやるべき事なのでしょうか?実はSumCalculatorという名の新しいクラスを作って、その中にパブリックメソッドとして書くのが正しいのではないでしょうか?
別クラスのパブリックメソッドとする
プライベートなメソッドのテストを書きたいということは、実はテスト対象の責務が多すぎることを示唆している場合があります。テストがどうしても書きたい場合は、その責務はテスト対象のプライベートな振る舞いでは無く、誰かのパブリックな振る舞いなのでしょう。テスト対象のプライベートメソッドを「クラスの抽出」や「メソッドの移動」を使って、テスト対象のコラボレータのパブリックメソッドとして抽出し、普通にパブリックメソッドとしてテストしましょう。

他の方法

ここまで書いておいてなんですが
  1. calcSumのテストと実装をパブリックで書く
  2. calcAverageのテストと実装をパブリックで書く
  3. リファクタリングでcalcSumメソッドの可視性をプライベートにして、calcSumのテストは削除
という手もあるかと思います。というかこちらのほうが自然ですね。せっかく書いたテストを捨ててしまうのは勿体無い気がしますが、実装中に書いたテストと最後に残すテストを同じにしなければならないというルールはありません。calcSumはcalcAverageを通してテストされているので良しとしましょう。

そんなこんなでプライベートメソッドのテストは必要ない!!・・・のではないかと最近思い始めました。

エリクサーは最後まで使わないタイプです

adingoアルバイターの @mururururu です。
主にFluctというSSPのRTB周りを担当しています。

FluctのRTBサーバは Erlang で書かれており、個人的にも Erlang 周りの技術に注目しています。
今回はあえて Erlang ではなくErlangVM 上で動くプログラミング言語 Elixirについて紹介してみます。

Elixirは Clojure, Ruby などの言語から強い影響を受けている動的型付き(関数型)言語です。JVM上で動くScalaがJavaの資産を活用できるように、ElixirもErlangの軽量プロセスを用いた並列処理、耐障害性などの特徴をフルに利用することが出来ます。
そんなElixirの魅力的なところを少し紹介してみます。

パターンマッチ

関数型言語によくあるやつですね。
データ構造から情報を抽出する機能とでも言うのでしょうか。実際の例を見た方が早いと思います。
 
{ x, y } = { 1, 2 }
x #=> 1
y #=> 2

左辺が右辺にマッチするように変数に値が束縛されます。

また、関数の引数でパターンマッチしマッチした節を実行する、というような使い方もします。

defmodule Fib do
  def fib(0), do: 1
  def fib(1), do: 1
  def fib(n), do: fib(n-1) + fib(n-2)
end

Fib.fib(5) #=> 8

フィボナッチ数列です。if文などは一切出てきません。

そして個人的にはかなり便利だと思っているバイナリのパターンマッチです。対象の長さ、エンディアン、また数値型として取り出すかバイナリ型として取り出すかなど細かく指定できます。バイナリプロトコルのパースなどがかなり簡潔に書けます。

例えば、先頭の符号なし16ビット整数が取り出したいデータの長さ(オクテット長)を表し、その後に目的のデータが続くようなバイナリから、そのデータを取り出す関数は以下のような感じになります。

def parse(<< length :: [size(16), big, unsigned, integer],
                     data :: [size(length), binary, unit(8)],
                     rest :: binary >>)
  { data, rest }
end

引数でパターンマッチするだけで終わってしまいます。パターンマッチの強力さが少しは伝わったでしょうか。

軽量プロセス

Elixirの特徴といえばなんといっても軽量プロセスです。軽量プロセスはErlangVM上でそれぞれ独立して動き、データを共有しません。GCもプロセスごとに行われます。プロセス同士のやりとりは基本的には非同期なメッセージングのみです。それによりErlangVMはそれぞれのプロセスの実行を勝手にマルチコアに分散することができます。
多くのElixirのアプリケーションではそういった多数の独立した軽量プロセスがメッセージをやりとりしながら協調する動作モデルとなっています。

以下は map関数を並列に行う例です。

defmodule Parallel do
  def pmap(collection, fun) do
    me = self()

    collection
    |> Enum.map(fn(elem) ->  
         spawn_link(fn -> (me <- { self(), fun.(elem) }) end) 
       end) 
    |> Enum.map(fn(pid) ->
         receive do 
           { ^pid, result } -> result 
         end
       end)
  end
end

Parallel.pmap(1..10000 fn(x) -> x + 1 end)
#=> [2, 3, 4, …]

文法を説明せずにこれを解説するのはちょっとつらいのですが、かいつまんで説明を試みてみます。まず、

Enum.map(fn(elem) ->  
  spawn_link(fn -> (me <- { self, fun.(elem) }) end) 
end)

spawn_linkは新たなプロセスを生成し引数で渡した無名関数をそのプロセスで実行させる関数です。ここでは collection の各要素それぞれに対してプロセスを生成し、そこで実際の処理を行わせ、その結果を"<-"演算子で生成元のプロセスにメッセージとして送信しています。

Enum.map(fn(pid) ->
  receive do 
    { ^pid, result } -> result 
  end
end)

ここでは各要素に対してメッセージを待ち受け、結果を受け取る処理をしています。

この関数は実際にマルチコアで実行されます。

マクロ

Lispとかにあるあれです。
ElixirのプログラムのASTはElixirのデータ構造を用いて表現されており、Elixirのプログラムは自身のASTを操作することができます。

実際にどういった場面で使われているかを標準添付のユニットテストライブラリであるExUnitを例に見てみます。
以下はExUnitのアサーションです。
 
  assert 2 > 3 

これは正しくないので、もちろんテストは失敗します。
実際にこれを実行してみると、

  ** (ExUnit.ExpectationError)
               expected: 2
    to be more than: 3

というエラーメッセージが表示されます。
 
もしassertがただの関数であるならば "2 > 3" の結果、つまり false が assert に引数として渡されます。そうするとエラーメッセージにこのような詳細な出力をすることはできません。
実際には assert はマクロとして実装されており、"2 > 3" の ASTである {:>, [], [2, 3]} を受け取りそれを操作することにより適切なエラーメッセージを出すことができています。 

まとめ

いかかでしょうか。Elixirの楽しげなところが少しでも伝わったらうれしいです。
かなりErlangに寄り添っているのでErlangを書いてる人から見れば何をいまさら、という感もありますが、細かいところの使い勝手はなかなかよくなっていて個人的にはとても気に入っています。
最近では、オライリーから本が出版されたり、海外で実際にプロダクション環境で運用されるケースも出てきていたりと盛り上がり始めているようです。

かなりおもしろい言語ですのでぜひ触ってみてください。
ではでは。

adingoでは一緒に働いてくださる仲間を募集しています。
VOYAGE GROUPや広告配信に興味を持たれましたら、気軽にご連絡ください。
http://voyagegroup.com/crew/recruit/ 
記事検索
QRコード
QRコード