Elixir inproduction

0
-1

Published on

Elixir Meetup #1 in Drecom

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
0
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
0
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Elixir inproduction

  1. 1. Elixir in Production Elixir Meetup #1 in Drecom
  2. 2. Agenda • 発表の趣旨 • 自己紹介 – 最近のElixir事情 • 運用システム構成 – 利用しているツール/ライブラリ群 • 運用(負荷テスト)時のトラブル(とその地雷処理) – 事例1.ログ – 事例2.コネクションプール – 事例3.アセット – その他 • まとめ
  3. 3. 発表の趣旨 • 本番運用事例の紹介をする事で – 本番採用事例が増える一助に – 採用ハードルが少しでも低く • 本番運用時のトラブル対応の紹介をする事で – あるあるの事例と思うので、知見共有する事で同 様のトラブル回避の手助けに なったら良いなと思います
  4. 4. 自己紹介 • おーはら(@ohrdev) • 写経(仏教的)/仏像彫り/寺社仏閣 • 広告エンジニア(Drecom) – Erlang/Elixir/Phoenix – Ruby/Rails – (Lisp/Scala)
  5. 5. 最近のElixir事情 • コミックマーケットC89でPhoenix本発売 – アランビックの錬金術師 – http://hayabusa333.tumblr.com/ – BOOTH: https://hayabusa333.booth.pm/items/186705 • Elixir 1.2 released – https://github.com/elixir- lang/elixir/blob/v1.2.0/CHANGELOG.md
  6. 6. 最近のElixir事情 • Programming Elixir 1.2 (Dave Thomas) – https://pragprog.com/book/elixir12/programming -elixir-1-2 – Β版 • Programming Phoenix – https://pragprog.com/book/phoenix/programmin g-phoenix – Β版
  7. 7. 運用システム構成 • 広告配信API/ミニコンテンツ(ゲーム) – F/W: maru( WAF/API DSL ) / Phoenix( WAF ) – DB: Redis( exredis + poolboy ) / Dynamo( ex_aws ) – Job: exq( + Sidekiq ) – 環境変数: dotenv – Deploy: exrm / mina / asset_sync(自製) – テスト: meck / power_assert – 監視: sentry( raven-elixir ) / monit / 社内監視tool – プロビジョニング: ansible( 自製galaxy-role ) – インフラ: AWS( EC2 / AutoScaling / ELB / S3 / CF )
  8. 8. 利用ツール/ライブラリ • WAF: – maru: https://maru.readme.io/ • 特徴: – シンプル/Api DSL(grape like) • 出来ない事: – セッション管理/DBコネクション/テンプレート描画 – Phoenix: http://www.phoenixframework.org/ • 特徴: – フルスタック(一通り揃ってる)/maruに比べると複雑 – アセットコンパイルはbrunch.ioを採用(node/npmが必要)
  9. 9. 利用ツール/ライブラリ • DB: – Redis: • exredis: https://github.com/artemeff/exredis • poolboy: https://github.com/devinus/poolboy – Dynamodb: • ex_aws: https://github.com/CargoSense/ex_aws – MySQL/PostgreSQL/Mongodb/etc • 弊社サービスでは採用していないのですが、恐らく ecto: https://github.com/elixir-lang/ecto 一択
  10. 10. 利用ツール/ライブラリ • Job: – exq: https://github.com/akira/exq (+ sidekiq) – http://qiita.com/ohr486/items/9db88866786ee8b b89d9 • 環境変数: – dotenv: https://github.com/avdi/dotenv_elixir
  11. 11. 利用ツール/ライブラリ • エラー監視(sentry): – raven-elixir: https://github.com/vishnevskiy/raven-elixir
  12. 12. 利用ツール/ライブラリ • 死活監視/自動再起動 – monit • DB/ミドルウェア/外部サービスの監視 – supervisor(OTP) • 言語の一部(OTP)として提供される • きちんとチューニング/設定しておくと安心できる – 半年の本番運用で2回程お世話になった – パラメータの設定不備でプロセスが死亡する事象が発生した が、自動的にプロセスを監視/再起動して、サービスを落す事 なく復旧/修正まで凌げた
  13. 13. 利用ツール/ライブラリ • プロビジョニング: – ansible + galaxy-role: https://galaxy.ansible.com/detail#/role/2930 – Erlang/Elixir/Phoenix のバージョンupの頻度はか なり早いので、自動化しておくべき – ErlangとElixirのバージョンの相性がある為、両方 のバージョンを指定できると捗る
  14. 14. 運用(負荷テスト)時のトラブル • Elixirの開発/本番運用を約1年程やってきて、 地雷はそれなりに踏み抜いてきました • 今回は特に – 開発時には発見し辛く、負荷テスト/本番運用時 に現れる – サービス規模/トラフィックがある程度大きくなるま で現れない といった事例をピックアップしています
  15. 15. 事例1.ログ • 事象:大したリクエスト数でもないのに、iowait が高まりLA / CPU使用率が上昇
  16. 16. 事例1.ログ • 検証: – サンプル http://github.com/falood/maru_examples – abで負荷をかけて計測(echo_server) $ ab -n 10000000 -c 2 http://xxx.xxx.xxx.xxx:8800/ $ vmstat -a 1
  17. 17. 事例1.ログ • 検証: – vmstatの結果: boが異常値 $ vmstat -a 1 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu----- r b swpd free inact active si so bi bo in cs us sy id wa st 2 0 0 6807288 45796 562724 0 0 21 1242 11712 5338 37 25 30 8 0 1 1 0 6807156 45796 562988 0 0 0 4528 28259 5784 15 15 51 20 0 1 1 0 6806908 45800 563184 0 0 0 4484 28252 5717 15 16 50 20 0 0 1 0 6806660 45796 563384 0 0 0 4548 28171 5843 15 16 50 19 0 2 0 0 6806412 45796 563584 0 0 0 4556 28003 5825 15 15 51 20 0 1 1 0 6806288 45796 563780 0 0 0 4484 28262 5787 15 16 50 20 0 1 1 0 6806040 45796 563984 0 0 0 4488 28604 5868 14 17 50 19 0 2 1 0 6805792 45796 564180 0 0 0 4472 28473 5888 13 18 50 19 0 1 1 0 6805668 45800 564384 0 0 0 4480 28193 5772 15 16 50 19 0 1 1 0 6805420 45796 564580 0 0 0 4472 28356 5746 14 17 50 20 0 2 0 0 6805420 45796 564784 0 0 0 4492 28445 5757 14 16 50 19 0 1 1 0 6805172 45796 564980 0 0 0 4504 28393 5787 15 16 50 20 0 1 1 0 6804924 45796 565184 0 0 0 4456 28411 5671 13 17 50 20 0 2 0 0 6804676 45796 565380 0 0 0 4488 28169 5786 14 15 51 20 0 1 1 0 6804428 45800 565576 0 0 0 4504 28053 5761 13 17 50 20 0
  18. 18. 事例1.ログ • 検証: – loggerのbackendがデフォルト(console)だと、 O_SYNCモードでログファイルがopenされる https://github.com/erlang/otp/blob/maint/erts/etc/com mon/run_erl_common.c – naoyaさんの記事(Linux I/O のお話 write 編) http://d.hatena.ne.jp/naoya/20070523/1179938637 – 『アプリケーションがSYNCモードでファイルを開い ていたり、明示的にfsync() してたりするとそこで waitが発生するのはいわずもがな、です。』
  19. 19. 事例1.ログ • 事象:大したリクエスト数でもないのに、iowait が高まりLA / CPU使用率が上昇 • 原因:loggerのバックエンドがデフォルトの consoleだった(為、ログファイルをO_SYNC モードで開いていた)ので、毎秒ディスクへの 同期とフラッシュが走っていた
  20. 20. 事例1.ログ • 対応 – 本番環境のloggerのbackendをconsoleから変更 – ※ ElixirのLoggerのbackendは公式にはconsoleし か提供されていない • https://github.com/elixir- lang/elixir/tree/master/lib/logger/lib/logger/backends • https://github.com/onkel-dirtus/logger_file_backend • https://github.com/basho/lager – logger_file_backendはカスタマイズに難ありだっ たのでbackendを自前実装した
  21. 21. 事例1.ログ • 教訓: – 本番環境のログのbackendは必ずfileベースのも のに変更すること – 負荷テスト時のサーバー状況のチェックは必ず実 施する事(あたりまえですが)
  22. 22. 事例2.コネクションプール • 事象:リクエストを大量に長時間なげ続け ると、ElasticCache(Redis)のコネクション数が あふれる
  23. 23. 事例2.コネクションプール • 状況: – 各種DBドライバのコネクション管理事情 • PostgreSQL/MySQL/MSSQL/SQLite3/MongoDB – ecto: https://github.com/elixir-lang/ecto – コネクション管理(内部的にはpoolboyで実装)を含む • Redis – exredis: https://github.com/artemeff/exredis – クライアントのみ、コネクション管理は含まれない • Dynamodb – ex_aws: https://github.com/CargoSense/ex_aws – APIベースなのでコネクション管理なし – Read/Write Capacity Unitの設定で担保
  24. 24. 事例2.コネクションプール • 状況: – (コネクション管理をしていなかったので)リクエスト 毎にRedisのコネクションを確立していた – ElasticCache(Redis)のコネクション • コネクションタイムアウト:デフォルト5分 • コネクション上限数:2万 – 開発時は、コネクション数自体が少なく、上限に いくまでにタイムアウトで切断されていたので気 がつかなかった、高負荷をかけて初めて発覚
  25. 25. 事例2.コネクションプール • 事象:リクエストを大量に長時間なげ続け ると、ElasticCache(Redis)のコネクション数が あふれる • 原因:Redisのコネクション管理をしていなかっ た/するドライバを使っていなかった
  26. 26. 事例2.コネクションプール • 対応: – コネクション管理を含むRedisドライバを使用 • https://github.com/quarkgames/exredis_pool • https://github.com/le0pard/redis_pool • 問題点: コネクションプールの設定が貧弱/十分に チューニングできない – poolboyでコネクションプールを自前実装 • 参考: たのしいpoolboy(@hagiyatさん) • http://qiita.com/hagiyat/items/a28683d01223bfc204d 9
  27. 27. 事例2.コネクションプール • 教訓: – Redisを使う際は、コネクション管理に注意、必ず コネクション管理機構を実装する事 – poolboyは良実装(Erlangの良いお手本コード) – 負荷テスト時のサーバー状況のチェック(ry
  28. 28. 事例3.アセット • 事象:AWSのデータ転送量の費用が増大 • 原因:EC2上にdeployしたphoenixアプリのア セット(画像/css/js/font/etc)の転送量だった
  29. 29. 事例3.アセット • Phoenixのアセットの参照: – digest: 静的ファイルを圧縮してmanifestを作成 • phoenix.digest (mixコマンド) • manifest.jsonに、圧縮前後のファイルパスのmapping をJSON形式で出力する – cache_static_manifest != true (config.exs) • 静的ファイルを priv/static 以下から参照 – cache_static_manifest == true (config.exs) • manifest.jsonをパースして、ets(ErlangのIn-memoryスト レージ)にマッピング情報をストア • 静的ファイル参照時に、圧縮後のファイルを参照させ る
  30. 30. 事例3.アセット • 改善前の手順 – 1. アセットの参照方法をmanifestに – 2. 圧縮ファイルとmanifest.jsonを作成 • MIX_ENV=prod mix phoenix.digest – 3. MIX_ENV=prod でアプリを起動 – 4. 2.のマッピング先(圧縮後ファイル)が参照 # config/prod.exs config :my_app, MyApp.Endpoint, http: [port: xxxx], url: [host: “xxxx”], cache_static_manifest: “priv/static/manifest.json”, server: true
  31. 31. 事例3.アセット • アセット参照の実体(static_path/2) – Phoenix.Route.Helpers # static_path/2 • https://github.com/phoenixframework/phoenix/blob/ master/lib/phoenix/router/helpers.ex – MyApp.Web # web ( web/web.ex ) • import MyApp.Router.Helpers – static_path/2 がimportされて利用可能に – View/css/javascript # static_path/2 • static_path/2 でアセットを参照
  32. 32. 事例3.アセット • アセット参照の実体(priv/static参照) – http://xxx.xxx.xxx.xxx:4000/images/hoge.png • priv/static/images/hoge.png が参照される – http://xxx.xxx.xxx.xxx:4000/css/var.css • priv/static/css/var.css が参照される
  33. 33. 事例3.アセット • 対応: – Phoenixにはasset_sync相当のライブラリが(自分 が調べた限り採用できそうなのものが)存在しな かった – Railsのasset_sync相当のライブラリを自前実装 • 対象ファイルのアセットファイルをs3にupload • static_path/2を、s3/cloudfrontを参照しにいく様に差換 える • アセットファイルをバージョン管理(sync/cleanup)
  34. 34. 事例3.アセット • 対応: – asset_sync(phoenix版)は、もう少し本番運用した 後、hexに公開予定 – 仮リポジトリ/参考実装(テスト/ドキュメント/残ン 実装対応中): • https://github.com/ohr486/asset_sync – 注意: • 2016/1 現在、ex_awsのs3は東京リージョンから一部機 能が利用できません • https://github.com/CargoSense/ex_aws/pull/101 の修正がhexにpublishされるまでパッチを当てるなりし て下さい
  35. 35. 事例3.アセット • 教訓: – インフラコストはちゃんと監視する事 – Phoenix on AWSで画像を扱う際は、転送量に注 意、必要に応じてCloudFrontへ – 負荷テスト時のサーバー状況のチェック(ry
  36. 36. その他 • 地雷処理の為にやった事/必要だった事 – ドキュメント(英語)を読む • 日本語の情報はまだまだ不足 – 実装コード(Elixir/Erlang)を読む • Erlangの参照ライブラリを読むケースはそれなりにある (ErlangのライブラリをwrapしただけのElixirライブラリ) – awesome-elixir/awesome-erlangのチェック • 他の実装ライブラリや、似た様な機能を探す際に便利、 定期的に追いかけておくと何かと捗る
  37. 37. その他 • 地雷処理の為にやった事/必要だった事 – 地雷処理できる人を増やす活動 • Erlangが読めるように – Elixir独自の機能はありますが、やはりベースはErlangです – ErlangをRubyのSyntaxで記述している感じ • OTPの概念を理解できるように – OTPの理解無しにElixirのアプリ運用はできない(と感じた) • 関数型言語を理解する – 社内勉強会(すごいE本/コップ本読書会) – Erlangに自信が無い場合は、時雨堂さんにコンサ ルをお願いすれば良いんじゃないでしょうか
  38. 38. まとめ • 弊社にて運用しているElixirのサービスについ ての紹介をしました • 本番運用時に発生したトラブルとその対応を 紹介しました • (完璧では無いですが)十分に本番で運用でき ています • まだまだ足りない機能/ライブラリがあるので、 もっと充実してきて欲しいです(自分ももっと公 開していきます)
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×