running-elixir-in-production
TRANSCRIPT
Running Elixir in Production2016-09-03 RubySapporo.beam おおはら つねのり
Oohara Tsunenori
beamlang.tokyotokyo.ex
Elixir
をProduction
で使う
なんて
正気ですか ?確か
に癖はチョッ
トあるけど筋の良い
通った言語ですよ
いやいや
子曰、学而時習之、不亦説乎、有朋自遠方来、不亦楽、人不知而不慍、不亦君子乎。『論語』
提供
株式会社えにしテックhttp://www.enishi-tech.com/
株式会社ファームノートhttp://farmnote.jp/
From Sapporo, with Love for Ruby & Beam.
RubySapporo.beamFrom Tokyo, with Love for Elixir.
beamlang.tokyotokyo.ex
Agenda
自己紹介|> 趣旨|> 開発環境|> 開発|> (負荷 )テスト|> 運用初期〜|> 運用中後期
|> コミュニティ|> まとめ
自己紹介• おーはら@ohrdev• 札幌 (学生 ,SIer:10年 ) => 東京 (web系 :5年 )• RubySapporoNightがきっかけで Rubyに◯◯◯–大通り近くの AppleStoreで島田さんが定期開催• ボブおじさん、パターン、 etc の紹介 LTに刺激
– SapporoRubyKaigiは皆勤 (多分 )• 東京で Elixir関係のmeetup ・イベントを主催 /運営– ElixirMeetup,tokyo.ex,phoenixハンズオン ,VR.tokyo
• Rubyの会社のサーバーサイドエンジニア• 普段使っている技術– Elixir/Erlang/Ruby/Lisp/AWS/etc
• Elixirの運用アプリ : 本番 x2、開発・検証 x1– Elixirアプリ : 運用 1年半 , elixir1.0 -> elixir1.3.1– Phoenixアプリ : 運用 1年 , phoenix0.14 -> phoenix1.2
よろしくおねがいします🙇
趣旨• 今日のゴール– Elixirのプロダクション運用 /開発事例を紹介– (私が )運用 /開発フェーズで踏んだ地雷と地雷処理内容を紹介–導入にあたって気をつけると捗るポイントを知る
• 目論見– Elixirの導入の一助に–コミュニティの活性化の一助に
開発環境• vim/atom (IDEを使ってるメンバーは居ない–特に理由はない、公式的には emacs推奨 (らしい )– plugin: vim-elixir
• バージョン管理–開発 : kerl + exenv※elixirのバージョンは erlangのバージョンに依存–本番 : ansible + AMI
• CI– Jenkins + mix test
開発環境• バージョンアップ、 deployment周りについては– http://www.slideshare.net/ohr486/running-web-ap
p-on-elixir をご参照ください
• 基本的な考え方は Railsとあまり変わらない–強いて言うなら、 Elixirだけでなく、 Erlangのバージョンも一緒に上げていく所
• Elixirのバージョンは Erlangのバージョンに依存する為
開発• 単体テスト–モックライブラリ• meck : https://github.com/eproxus/meck• mock : https://github.com/jjh42/mock
–モックライブラリに癖があるので、きちんとテスト設計しないとメンテ不可能になる場合も・・・• TDD– Ruby + Guard + mix test– phoenix_live_reload
開発 :tips
• mockライブラリ– :meck (erlang)• 癖がある• Test毎に定義したモックを unloadする必要がある
– unloadしないとモック内容が別の testでも有効になる• 定義していないモックを unloadすると not_mocked
error– 特定の Testでのみ setupでまとめて unloadできない
– Mock (elixir)• meckの面倒な処理をまとめて行うマクロ• 細かいところには手は届いていない
DEMO😛
(負荷 )テスト• observerがとても手軽 &便利– observer監視をネットワーク越しにやると捗る–アイデア
• ローカルの Erlangノードと、サーバー上の Erlangノードに名前をつけて、 cookie(セキュリティ用のキー )を設定• ローカルの Erlangノードと、サーバー上の Erlangノードを通信可能にする( sshでトンネルを掘る)
• ガリガリやるなら専用のベンチツールを
(負荷 )テスト :tips
• observer– GUIサーバーモニタリングツール–利用するには Erlangのコンパイル時に、 ws(wxWidgetsの Erlangバインディング )を有効にしないと利用できない– iex(1)> :bserver.start– erl –run observer
DEMO😛
(負荷 )テスト :tips• empd: Erlang Port Mapper Daemon–分散 Erlang環境におけるノードの名前解決を行う–使用ポートはデフォルトで 4369
• ノード間の通信ポート– inet_dist_listen_min, inet_dist_listen_max で指定可能、 VMのパラメータとして起動時に渡す
(負荷 )テスト :tips
• 分散 Erlangのノード間の通信ポート– inet_dist_listen_min、 inet_dist_listen_maxで使用するポートの範囲を指定可能– VMの起動オプションとして引き渡す
(負荷 )テスト :tips
Remote Server Local Server
epmd epmd
EralngVMname:remote
EralngVMname:monitor
sshdsshd
DEMO😛
Port 4369Port 4369
Port 9001 Port 9001〜 5
Port 22
ssh –N –L 9001:localhost:9001 –L
4369:localhost:4369 root@remotehost
erl -name [email protected] -setcookie my-cookie -run observer
iex --name [email protected] --cookie my-cookie --erl “-kernel inet_dist_listen_min 9001 inet_dist_listen_max 9001” –S mix
運用初期〜• リリース時: 5000DAU -> 現在 :60万 DAU• トラフィックが増えた時にトラブルは起こる– DBのコネクション数増加–ログのローテーション–ログ出力に伴う I/O負荷– (phoenixアプリの )データ転送量が増大
運用初期 :tips(redis)
• DBコネクションの増加– Ecto : コネクション管理機能がバンドル• https://github.com/devinus/poolboy
– Redis: コネクション管理機能を含まない場合あり• https://github.com/artemeff/exredis• 意識せずに書くと、 1Req=1Process=1Connectionに
運用初期 :tips(redis)
Our Appfront
P P
RedisP P
P P
P P
Request Handling process Redis Client
Handling process毎にRedis Client(コネクション )を作ると・・・
リクエストの数だけRedisへのコネクションができてしまう
Timeoutで接続が切れるまでコネクションが残るのでtoo many connection error!
運用初期 :tips(redis)
Our Appfront
P P
RedisP P
P P
P
Request Handling process Redis Client
worker pool
poolboy
予め Client(worker)をプーリングしておく
プールの中の workerを使い回す
運用初期 :tips(log1)
• ログのローテーション– (exrmで releaseした場合、デフォルトだと )ログファイルは、 erlang.log.1,erlang.log.2,… と吐かれる–デフォルトの設定だと• 100キロバイト毎に新しいファイルに• 世代数は 5、それ以上はローテ(古いのが消える )する
–高トラフィック (ログが大量に吐かれる )と古いログが消えてしまう
運用初期 :tips(log1)
• ログのローテーションの設定–環境変数で変更可能• http://www.erlang.org/doc/man/run_erl.html
– RUN_ERL_LOG_MAXSIZE• ログローテーションが走るサイズ
– RUN_ERL_LOG_GENERATIONS• 世代管理数
–上の 2つの設定値を調整してログが消えないようにする
運用初期 :tips(log2)
• ログ出力に伴う I/O負荷– Elixirの Loggerはバックエンドを指定できる• 現状、 backendは consoleのみ( fileはない)• デフォルトのままログを出力すると、 consoleモードでログが出力される• consoleモードだと、ログを同期書き込み (o_sync)を行う(ので負荷が高い )
– logger_file_backend を使おう• https://github.com/onkel-dirtus/logger_file_backend
運用初期 :tips(画像 )
• 前提 : AWSの EC2上の phoenixアプリ• Phoenixアプリの画像の実態は、– APP_ROOT/priv/images 以下のファイル
AWS Private Network
EC2 instance
ROOT/priv/images/xxxxx
GW
Image files データ転送量、すごく・・・お高いです・・・
運用初期 :tips(画像 )
• priv以下のアセットファイルを CDNに転送• phoenixの static_pathの参照先を CDNに– https://github.com/ohr486/asset_sync
AWS Private Network
EC2 instance
ROOT/priv/images/xxxxx
GW
AWS CloudFront
priv/images/xxxxx
asset_sync
運用中後期• 日々のチェック–エラー検知• sentryでエラーを通知• Clientは ravenを使用
– https://hex.pm/packages/raven
–サーバーメトリクス• AWS CloudWatch で取得• NewRelic (erlangのライブラリ )
– https://github.com/wooga/newrelic-erlang
運用中後期 :tips(sentry)
• Setnryへの通知–スタックトレースは、 erlangの get_stacktrace/0で取得– http://erlang.org/doc/man/erlang.html#get_stacktrac
e-0–最後に起こった例外を取得できる
運用中後期 :tips(sentry)
運用中後期 :tips(newrelic)
• NewRelicのクライアント– https://github.com/wooga/newrelic-erlang– Newrelicのメトリクス endpointを httpで叩いてるけど、正式なものではないので使わない方が無難
• https://discuss.newrelic.com/t/erlang-interaction-with-collector-newrelic-com/4900/2• Cの AgentSDKがあるのでそちらを使ってくれとのこと
– https://docs.newrelic.com/docs/agents/agent-sdk/getting-started/new-relic-agent-sdk
– (datadogで良いのでは・・・ )
コミュニティ• 少ない– 知見共有の場や、どうしても困ったときの駆け込み寺になるので多い方が良い(よね?)– ruby: コンサルいっぱい、 xxx.rbで相談– Erlang: 時雨堂、コンサル数人– Elixir: コンサル数人
• Elixir– 徐々に増えつつある
• Erlang– 定期開催は sapporo.beamくらい?– (計画中 (tokyo.erl?))
まとめ• プロダクション運用の中で踏んだ地雷について紹介しました• 地雷の処理について紹介しました• Elixirのプロダクション導入の一助になれば幸いです