SlideShare a Scribd company logo
Running Elixir in Production
2016-09-03 RubySapporo.beam
おおはら つねの
Ooharabeamlang.tokyo
Elixi
r
Productio
n

使
う
 正気
? 癖チョッ
ト
 筋
良
い
通っ
た言語
いやい
や
子曰、学而時習之、不亦説乎、
有朋自遠方来、不亦楽、
人不知而不慍、不亦君子乎。
『論語』
提供
株式会社えにしテック
http://www.enishi-tech.com/
株式会社ファームノート
http://farmnote.jp/
From Sapporo, with Love for Ruby & Beam.
RubySapporo.beam
From Tokyo, with Love for Elixir.
beamlang.tokyo
tokyo.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-
app-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の面倒な処理をまとめて行うマクロ
• 細かいところには手は届いていない
(負荷)テスト
• observerがとても手軽&便利
– observer監視をネットワーク越しにやると捗る
– アイデア
• ローカルのErlangノードと、サーバー上のErlangノード
に名前をつけて、cookie(セキュリティ用のキー)を設定
• ローカルのErlangノードと、サーバー上のErlangノード
を通信可能にする(sshでトンネルを掘る)
• ガリガリやるなら専用のベンチツールを
(負荷)テスト:tips
• observer
– GUIサーバーモニタリングツール
– 利用するにはErlangのコンパイル時に、
ws(wxWidgetsのErlangバインディング)を有効にし
ないと利用できない
– iex(1)> :bserver.start
– erl –run observer
(負荷)テスト: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
EralngVM
name:remote
EralngVM
name:monitor
sshdsshd
Port 4369Port 4369
Port 9001 Port 9001〜5
Port 22
ssh –N –L
9001:localhost:9001 –L
4369:localhost:4369
root@remotehost
erl -name monitor@127.0.0.1 -setcookie my-cookie -run observer
iex --name remote@127.0.0.1 --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 App
front
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 App
front
P P
RedisP P
P P
P
Request Handling process Redis Client
worker pool
pool
boy
予め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/imag
es/xxxxx
G
W
Image
files データ転送量、すご
く・・・お高いです・・・
運用初期:tips(画像)
• priv以下のアセットファイルをCDNに転送
• phoenixのstatic_pathの参照先をCDNに
– https://github.com/ohr486/asset_sync
AWS Private Network
EC2 instance
ROOT/priv/imag
es/xxxxx
G
W
AWS CloudFront
priv/images/x
xxxx
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_stacktra
ce-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のプロダクション導入の一助になれば幸
いです

More Related Content

running-elixir-in-production