running-elixir-in-production

32
Running Elixir in Production 2016-09-03 RubySapporo.beam おおおお おおおお Oohara Tsunenori beamlang.tokyo tokyo.ex Eli xir Product ion おお ををを おお をを を? ををを おおおお をををを おお おおお おお ををを おおおお

Upload: tsunenori-oohara

Post on 15-Apr-2017

1.027 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: running-elixir-in-production

Running Elixir in Production2016-09-03 RubySapporo.beam おおはら つねのり

Oohara Tsunenori

beamlang.tokyotokyo.ex

Elixir

をProduction

で使う

なんて

正気ですか ?確か

に癖はチョッ

トあるけど筋の良い

通った言語ですよ

いやいや

Page 2: running-elixir-in-production

子曰、学而時習之、不亦説乎、有朋自遠方来、不亦楽、人不知而不慍、不亦君子乎。『論語』

Page 3: running-elixir-in-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

Page 4: running-elixir-in-production

Agenda

自己紹介|> 趣旨|> 開発環境|> 開発|> (負荷 )テスト|> 運用初期〜|> 運用中後期

|> コミュニティ|> まとめ

Page 5: running-elixir-in-production

自己紹介• おーはら@ohrdev• 札幌 (学生 ,SIer:10年 ) => 東京 (web系 :5年 )• RubySapporoNightがきっかけで Rubyに◯◯◯–大通り近くの AppleStoreで島田さんが定期開催• ボブおじさん、パターン、 etc の紹介 LTに刺激

– SapporoRubyKaigiは皆勤 (多分 )• 東京で Elixir関係のmeetup ・イベントを主催 /運営– ElixirMeetup,tokyo.ex,phoenixハンズオン ,VR.tokyo

Page 6: running-elixir-in-production

• Rubyの会社のサーバーサイドエンジニア• 普段使っている技術– Elixir/Erlang/Ruby/Lisp/AWS/etc

• Elixirの運用アプリ : 本番 x2、開発・検証 x1– Elixirアプリ : 運用 1年半 , elixir1.0 -> elixir1.3.1– Phoenixアプリ : 運用 1年 , phoenix0.14 -> phoenix1.2

Page 7: running-elixir-in-production

よろしくおねがいします🙇

Page 8: running-elixir-in-production

趣旨• 今日のゴール– Elixirのプロダクション運用 /開発事例を紹介– (私が )運用 /開発フェーズで踏んだ地雷と地雷処理内容を紹介–導入にあたって気をつけると捗るポイントを知る

• 目論見– Elixirの導入の一助に–コミュニティの活性化の一助に

Page 9: running-elixir-in-production

開発環境• vim/atom (IDEを使ってるメンバーは居ない–特に理由はない、公式的には emacs推奨 (らしい )– plugin: vim-elixir

• バージョン管理–開発 : kerl + exenv※elixirのバージョンは erlangのバージョンに依存–本番 : ansible + AMI

• CI– Jenkins + mix test

Page 10: running-elixir-in-production

開発環境• バージョンアップ、 deployment周りについては– http://www.slideshare.net/ohr486/running-web-ap

p-on-elixir をご参照ください

• 基本的な考え方は Railsとあまり変わらない–強いて言うなら、 Elixirだけでなく、 Erlangのバージョンも一緒に上げていく所

• Elixirのバージョンは Erlangのバージョンに依存する為

Page 11: running-elixir-in-production

開発• 単体テスト–モックライブラリ• meck : https://github.com/eproxus/meck• mock : https://github.com/jjh42/mock

–モックライブラリに癖があるので、きちんとテスト設計しないとメンテ不可能になる場合も・・・• TDD– Ruby + Guard + mix test– phoenix_live_reload

Page 12: running-elixir-in-production

開発 :tips

• mockライブラリ– :meck (erlang)• 癖がある• Test毎に定義したモックを unloadする必要がある

– unloadしないとモック内容が別の testでも有効になる• 定義していないモックを unloadすると not_mocked

error– 特定の Testでのみ setupでまとめて unloadできない

– Mock (elixir)• meckの面倒な処理をまとめて行うマクロ• 細かいところには手は届いていない

DEMO😛

Page 13: running-elixir-in-production

(負荷 )テスト• observerがとても手軽 &便利– observer監視をネットワーク越しにやると捗る–アイデア

• ローカルの Erlangノードと、サーバー上の Erlangノードに名前をつけて、 cookie(セキュリティ用のキー )を設定• ローカルの Erlangノードと、サーバー上の Erlangノードを通信可能にする( sshでトンネルを掘る)

• ガリガリやるなら専用のベンチツールを

Page 14: running-elixir-in-production

(負荷 )テスト :tips

• observer– GUIサーバーモニタリングツール–利用するには Erlangのコンパイル時に、 ws(wxWidgetsの Erlangバインディング )を有効にしないと利用できない– iex(1)> :bserver.start– erl –run observer

DEMO😛

Page 15: running-elixir-in-production

(負荷 )テスト :tips• empd: Erlang Port Mapper Daemon–分散 Erlang環境におけるノードの名前解決を行う–使用ポートはデフォルトで 4369

• ノード間の通信ポート– inet_dist_listen_min, inet_dist_listen_max で指定可能、 VMのパラメータとして起動時に渡す

Page 16: running-elixir-in-production

(負荷 )テスト :tips

• 分散 Erlangのノード間の通信ポート– inet_dist_listen_min、 inet_dist_listen_maxで使用するポートの範囲を指定可能– VMの起動オプションとして引き渡す

Page 17: running-elixir-in-production

(負荷 )テスト :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

Page 18: running-elixir-in-production

運用初期〜• リリース時: 5000DAU -> 現在 :60万 DAU• トラフィックが増えた時にトラブルは起こる– DBのコネクション数増加–ログのローテーション–ログ出力に伴う I/O負荷– (phoenixアプリの )データ転送量が増大

Page 19: running-elixir-in-production

運用初期 :tips(redis)

• DBコネクションの増加– Ecto : コネクション管理機能がバンドル• https://github.com/devinus/poolboy

– Redis: コネクション管理機能を含まない場合あり• https://github.com/artemeff/exredis• 意識せずに書くと、 1Req=1Process=1Connectionに

Page 20: running-elixir-in-production

運用初期 :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!

Page 21: running-elixir-in-production

運用初期 :tips(redis)

Our Appfront

P P

RedisP P

P P

P

Request Handling process Redis Client

worker pool

poolboy

予め Client(worker)をプーリングしておく

プールの中の workerを使い回す

Page 22: running-elixir-in-production

運用初期 :tips(log1)

• ログのローテーション– (exrmで releaseした場合、デフォルトだと )ログファイルは、 erlang.log.1,erlang.log.2,… と吐かれる–デフォルトの設定だと• 100キロバイト毎に新しいファイルに• 世代数は 5、それ以上はローテ(古いのが消える )する

–高トラフィック (ログが大量に吐かれる )と古いログが消えてしまう

Page 23: running-elixir-in-production

運用初期 :tips(log1)

• ログのローテーションの設定–環境変数で変更可能• http://www.erlang.org/doc/man/run_erl.html

– RUN_ERL_LOG_MAXSIZE• ログローテーションが走るサイズ

– RUN_ERL_LOG_GENERATIONS• 世代管理数

–上の 2つの設定値を調整してログが消えないようにする

Page 24: running-elixir-in-production

運用初期 :tips(log2)

• ログ出力に伴う I/O負荷– Elixirの Loggerはバックエンドを指定できる• 現状、 backendは consoleのみ( fileはない)• デフォルトのままログを出力すると、 consoleモードでログが出力される• consoleモードだと、ログを同期書き込み (o_sync)を行う(ので負荷が高い )

– logger_file_backend を使おう• https://github.com/onkel-dirtus/logger_file_backend

Page 25: running-elixir-in-production

運用初期 :tips(画像 )

• 前提 : AWSの EC2上の phoenixアプリ• Phoenixアプリの画像の実態は、– APP_ROOT/priv/images 以下のファイル

AWS Private Network

EC2 instance

ROOT/priv/images/xxxxx

GW

Image files データ転送量、すごく・・・お高いです・・・

Page 26: running-elixir-in-production

運用初期 :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

Page 27: running-elixir-in-production

運用中後期• 日々のチェック–エラー検知• sentryでエラーを通知• Clientは ravenを使用

– https://hex.pm/packages/raven

–サーバーメトリクス• AWS CloudWatch で取得• NewRelic (erlangのライブラリ )

– https://github.com/wooga/newrelic-erlang

Page 28: running-elixir-in-production

運用中後期 :tips(sentry)

• Setnryへの通知–スタックトレースは、 erlangの get_stacktrace/0で取得– http://erlang.org/doc/man/erlang.html#get_stacktrac

e-0–最後に起こった例外を取得できる

Page 29: running-elixir-in-production

運用中後期 :tips(sentry)

Page 30: running-elixir-in-production

運用中後期 :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で良いのでは・・・ )

Page 31: running-elixir-in-production

コミュニティ• 少ない– 知見共有の場や、どうしても困ったときの駆け込み寺になるので多い方が良い(よね?)– ruby: コンサルいっぱい、 xxx.rbで相談– Erlang: 時雨堂、コンサル数人– Elixir: コンサル数人

• Elixir– 徐々に増えつつある

• Erlang– 定期開催は sapporo.beamくらい?– (計画中 (tokyo.erl?))

Page 32: running-elixir-in-production

まとめ• プロダクション運用の中で踏んだ地雷について紹介しました• 地雷の処理について紹介しました• Elixirのプロダクション導入の一助になれば幸いです