エンジニアの松原@ma2geです。 実はエムスリーでは数ヶ月前から Elixir を利用しております。現在私が関わっている商用プロダクトはグループ会社横断でエンジニアの有志が立ち上げたプロジェクトで、そのシステムの一部にて Elixir が稼働しております。Elixir が動いているのは広告配信に近い部分で多数の接続を捌く必要があり、アーキテクチャ検討時に普段チームで利用している Rails 含め検討した結果、適性のある Elixir を採用することに決定しました。
今回の記事ではエムスリーにおける現在の Elixir 開発環境周りについて書きます。書こうと思ったきっかけは melpon さんが Qiita に良い記事を公開されていたので、弊社からも1事例ということで公開できたらと思ったためです。
開発環境構築
少し前までは構築の手順があるだけで、以下のような課題がありました。
- 環境構築時のエラー対応
- Elixir 以外のアプリとの連携
環境構築時のエラー対応
Elixir のような新しい言語を採用し社内で扱っていくためには、普段別の言語で開発している人からするとそれなりに敷居があります。特に開発環境の構築では構築手順に従っていても環境差分のためにエラーが出たりということが起こりがちです。慣れていない言語で遭遇するエラーは時間も取られ嬉しくありません。
Elixir 以外のアプリとの連携
これは Elixir に限った話ではないですが、現在開発しているプロジェクトでは Elixir 単体のアプリケーションではなく、Rails で作られたアプリケーションと組み合わせる必要のあるものがあります。またほとんどのアプリケーションと同じでミドルウェア類も必要になっています。このため Elixir 単体の開発環境構築だけが簡単に済んでも、それ以外でつまづく可能性がありました。
Docker, Docker Compose で構築
これらを解決するために Docker と Docker Compose を使い、各種リポジトリを落としてきて docker-compose build
と docker-compose up -d
するだけで開発環境構築が完了するようにしています。今までの作業と比べてもかなりの手間を削減できていて、新しくプロジェクトへメンバーが加入してもすぐに環境構築し開発を始めることができるようになりました。余談ですがこれによって今週も Elixir を動かす開発者が一人増えました。
開発周りのルール
今のところ少人数ということもあり、そんなにルールはありません。今後開発者が増えるに従って随時変化していくでしょう。
コーディングルール
色々したいと思いつつ現状はそこまで人が多くないこともあり、コードレビューのみで進めています。Elixir 1.6 の formatter を心待ちにしています。1.6 が来たら CI と連携させるところまでやりたい。
テスト
テストは動的言語ということもあり多少手厚めにしており、カバレッジを 90% とることを目標にしています。カバレッジの取得には ExCoveralls を使っています。 カバレッジの取得方法については以前こちらに書いたので、よければ一例として参考にしてみてください。
デプロイ
弊社の園田@sonodar が書いてくれた "Elixir/Phoenix環境をElasticBeanstalk Custom Platformで構築してみた" の内容で構築されており、ElasticBeanstalk でのローリングアップデートによるデプロイをしています。Elixir のデプロイ周りはコンパイル済みバイナリを使ったデプロイが多いですが、ソースコード配置して起動しているところが珍しいかもしれません。
ただ Custom Platform を作る手間や、ElasticBeanstalk 周りのブラックボックス感が割と大変なこと、あと Distillery が割と標準的なリリース方法として使われているのでそっちに合わせたい、と、課題感も出てきており見直したいという話が上がっています。
ちなみになぜデプロイに Distillery のようなものを使うかについては、Adopting Elixir に載っていたので興味がある方は読んでみると良いと思います。
ライブラリ
ここまでで終わりにしようと思ったのですが、ちょっと分量的に寂しい感じになってしまったので現在使っているライブラリで主要なものを載せます。
- Phoenix Framework
- Web アプリケーションフレームワークがあると流儀に乗れるので便利です
- https://github.com/phoenixframework/phoenix
- Cowboy
- Erlang 製 HTTP Server いつもお世話になっております
- https://salt.bountysource.com/teams/ninenines から応援できます
- https://github.com/ninenines/cowboy
- LoggerFileBackend
- ログファイルを用途ごとに分けたくて使っています
- https://github.com/onkel-dirtus/logger_file_backend
- Timex
- 時間周りを扱うのに便利
- https://github.com/bitwalker/timex
- Poolboy
- コネクションプーリングのため導入
- Erlang 製
- https://github.com/devinus/poolboy
- ConCache
- ローカルでのキャッシュのため導入
- https://github.com/sasa1977/con_cache
- RemoteIp
- リモート側の IP 取得に使用
- README.md に比較表が書いてあるが、類似ライブラリと比べて X-Forwarded-For ヘッダーの扱いが正確だったので採用(使う際には Caveats の内容を読んでおくと良い)
- https://github.com/ajvondrak/remote_ip
- sentry
- 弊社では Sentry を使っているのでこちらを導入
- いつの間にか Sentry 公式になったんですね
- https://github.com/getsentry/sentry-elixir
- ExCoveralls
- Coverex を導入していましたが途中でこちらに切り替えました。理由は取られているカバレッジ結果がより正確そう(詳しく追えていない)、GitLab CI のサンプル例が ExCoveralls 使っていたため。
- https://github.com/parroty/excoveralls
- Power Assert
- テスト結果見やすいです、スターつけてください、お願いします
- https://github.com/ma2gedev/power_assert_ex
今後使いたい
- Credo
- コード品質向上のため
- https://github.com/rrrene/credo
- Sobelow
- セキュリティ周りのチェックとして
- https://github.com/nccgroup/sobelow
まとめ
4/1 の Elixir Conf Japan 2017 で LT した時には、まだ本番で動く Elixir アプリケーションがなかったのでフワっとした内容になってしまったのですが、今現在は Elixir が本番環境で動いていますので具体的な部分を書いてみました。
一緒に開発してくれる仲間を募集中です!
エムスリーでは Elixir だけでなく、Java、Scala、Ruby、Kotlin などが適材適所で大活躍してます。 一緒に開発する仲間を絶賛募集中です!メンバーとカジュアルに話す場も設けてますので是非気軽にお問い合わせください!