Create a gist now

Instantly share code, notes, and snippets.

実践 Erlang/OTP コトハジメ 2014.11

実践 Erlang/OTP コトハジメ 2014.11

更新:2014-11-20
バージョン:0.0.5
作者:@voluntas
URL:http://voluntas.github.io/

概要

実際に仕事で Erlang/OTP を使う際に必要になるポインタをまとめることにした。

躓きながら進むのも良いが、まずはポインタに沿って進みその後、色々考えて進むのが良いだろう。

情報

検索すればやまほど出てくるので、基本的には「まとまってる」という点でのポインタを上げる事にする。

日本語

書籍に関してはオーム社の プログラミング Erlang で問題ない。

Erlang/OTP の父が書いたこともあり、かなり基本を中心としてしっかりかかれている。ただしかなり古いので、あくまで基本的なところだけを参考にするべきだ。最新の Erlang/OTP (R16B03-1) では動かないところもあったりする。

もう一つ書籍では無いが Learn you some Erlang for great good! の日本語訳 もとても良い。

Learn you some Erlang for great good! は Heroku で働いている Fred が書いた。Heroku はルーティングメッシュやログ周りを Erlang/OTP で実装しているヘビーユーザだ。OTP 部分もかなり詳細に書かれているため、これを読めば一通り Erlang/OTP の内容が理解できるだろう。

このレベルの内容が日本語で読めるのは本当にありがたい。皆 @ymotongpoo に感謝すると良い。

注意点として、この本はライブラリ等の解説は含まれていない。

また Erlang のドキュメントを一部翻訳したモノも紹介しておこう。

Erlang Efficiencyガイド バージョン自体が古いので、今は使われていないものもある。ただ、幅広い範囲で知識を得られる。これを読んでから英語版を読めば理解しやすいだろう。

英語

かなりあるが、まずはなんといっても Programming Erlang: Software for a Concurrent World の 2nd だろう。これは プログラミング Erlang の原著である。

最新版はまだ出ていない R17 の機能である map なども含まれている。実は rebar の説明も入っていたりする。

次は少し古いが Erlang and OTP in ActionErlang Programming だろう。Erlang and OTP は OTP についてかなりわかりやすく書いてあるのでオススメだ。 Erlang Programming は EUnit などテストの話もしっかり書いてある。

もっと入門っぽいのが欲しければ Introducing Erlang もある。ただこれで学べるのは基本的に プログラミング Erlang に書いてある、日本語で読める文献があるのであまり読む機会はなさそうだ。

あとはドキュメントがかなり有用だ。Erlang/OTP のドキュメントはとてもよく出来ている。私はランチャーの検索対象に入れて、ローカルで検索して使っている。

ドキュメントは Erlang/OTP R16B03-1 で参照可能だ。

海外の情報は多すぎて書き切れない、検索すれば基本的にはぶつかると思うので、ここでは割愛。

開発環境(エディタ編)

Emacs

url:https://github.com/erlang/otp/blob/maint/lib/tools/emacs/erlang.el

基本は Emacs を使うべきだ。なぜならば Erlang/OTP のソースコードパッケージに erlang.el がふくまれているからだ。

基本的に Emacs 以外はオススメ出来ないのだが、残念ながら宗教上の理由でそれ以外の人のためにも紹介しておく。

VIM

url:https://github.com/vim-erlang/

私は残念ながら VIM なので Emacs の恩恵は受けられない。私はこの辺とオレオレ拡張を使っている。

IntelliJ

url:https://github.com/ignatov/intellij-erlang

IDE が欲しいなら IntelliJ がオススメだ。このプラグインの作者は IntelliJ の中の人だったりする。

じつは出来もかなりイイ。

Standalone Erlang IDE という名前からもかなり期待が持てる。メールするとバイナリが貰えたりするらしい。

Sublime Text

url:https://github.com/fjl/Sublime-Erlang

今人気の Sublime Text 向けも存在する。モダンな人はコレを使うと良い。

開発環境(OS 編)

開発環境も Windows 版があることもあり、幅広い。

Linux

本番へのデプロイはほとんどの場合、これだろう。というか Windows Server にデプロイした話を聞いたことが無い。なので実は開発も Linux ベースでやると良い。

多くの開発者はディストリとして Ubuntu を選択しているようだ。

Mac OS X

こちらも多いが、実際本番では使われないので開発専用。Halfword が使えなかったりと色々不満がある。

ただ、まぁ困ることはほとんど無い。

Windows

未経験なので何とも言えないのだが、ちゃんと Windows バイナリも用意されている Erlang/OTP です。

開発環境(Erlang/OTP ビルド編)

基本的にはソースコードからのインストールをオススメするが、Kerl を使ったり、Erlang Solutions からパッケージでもインストールできる。

さらに Mac であれば MacPorts や Homebrew でインストールすることも可能だ。ここでは時前ビルドを紹介する。

kerl を使ってインストール

url:https://github.com/spawngrid/kerl

kerl は複数の Erlang/OTP を管理してくれるツールだ。

日本語での解説があるのでコレを読めば大丈夫だろう。

http://qiita.com/tatsuya6502/items/f15da8ea6e793c5038a2

ソースコードからインストール

もし Java との接続を考えている場合は以下のサンプルは使えないので注意して欲しい

./configure --enable-smp-support \
            --enable-m64-build \
            --enable-native-libs \
            --disable-sctp \
            --enable-threads \
            --enable-kernel-poll \
            --enable-hipe \
            --without-javac

hipe や native-libs は有効にしてもデメリットになることは無いので採用することにしている。

Erlang Solutions からインストール

apt-get や yum でインストールが可能だ。windows や mac のバイナリも存在する。

https://www.erlang-solutions.com/downloads/download-erlang-otp

開発環境(ビルドツール編)

ビルドツールについては主に二種類ある。 rebarerlang.mk だ。

rebar

rebar で良いだろう。つい先日 2.2 が出たこともあり落ち着いている。

rebar のコンパイルはとても簡単だ。

$ git clone git@github.com:rebar/rebar.git
$ cd rebar
$ make

あとは rebar のバイナリが出来たのでそれを PATH が通ってる場所に置けば良い

rebar は compile から xref まで様々な機能が対応している。リリースもこれ一つで出来る。

CircleCI

URL:https://circleci.com/

自動ビルドツールもオススメしておきたい。Erlang/OTP 対応は多いが、時前のビルドが出来るようになる。

circle.yml:

dependencies:
  pre:
    - bash ./install-otp_src_R16B03.sh
  cache_directories:
    - otp_src_R16B03
test:
  pre:
    - ln -s ~/<application-name> ~/bin/erl
  override:
    - make

install-otp_src_R16B03.sh:

set -x
set -e
if [ ! -e otp_src_R16B03/bin/erl ]; then
  curl -O http://www.erlang.org/download/otp_src_R16B03.tar.gz
  tar xzf otp_src_R16B03.tar.gz
  cd otp_src_R16B03
  ./configure --enable-smp-support \
              --enable-m64-build \
              --enable-halfword-emulator \
              --disable-native-libs \
              --disable-sctp \
              --enable-threads \
              --enable-kernel-poll \
              --disable-hipe \
              --without-javac
  make;
fi

Erlang/OTP が無ければコンパイルしてインストールしてくれる。

makefile

rebar を Makefile でラッピングするのが Erlang/OTP 流らしい。難しい事はやっていないので、参考にして欲しい。

Makefile:

.PHONY: all compile deps clean test devrel rel

REBAR_CONFIG = rebar.config

APP_NAME =

all: clean deps test

deps: get-deps update-deps
        @./rebar -C $(REBAR_CONFIG) compile

update-deps:
        @./rebar -C $(REBAR_CONFIG) update-deps

get-deps:
        @./rebar -C $(REBAR_CONFIG) get-deps

compile:
        @./rebar -C $(REBAR_CONFIG) compile skip_deps=true
        @./rebar -C $(REBAR_CONFIG) xref skip_deps=true

devrel: rel
        $(foreach dep,$(wildcard deps/*), rm -rf dev/$(APP_NAME)/lib/$(shell basename $(dep))-* && ln -sf $(abspath $(dep)) dev/$(APP_NAME)/lib;)
        rm -rf dev/$(APP_NAME)/lib/$(APP_NAME)-*
        rm -rf dev/$(APP_NAME)/lib/$(APP_NAME)
        mkdir dev/$(APP_NAME)/lib/$(APP_NAME)
        ln -sf $(abspath ebin) dev/$(APP_NAME)/lib/$(APP_NAME)/ebin
        ln -sf $(abspath priv) dev/$(APP_NAME)/lib/$(APP_NAME)/priv

rel: compile
        mkdir -p dev
        mkdir -p deps
        (cd rel && rm -rf ../dev/$(APP_NAME) && ../rebar generate && ../rebar generate target_dir=../dev/$(APP_NAME))

test: compile
        rm -rf .eunit
        @./rebar -C $(REBAR_CONFIG) eunit skip_deps=true

clean:
        @./rebar -C $(REBAR_CONFIG) clean skip_deps=true

distclean: clean
        @./rebar -C $(REBAR_CONFIG) clean
        @./rebar -C $(REBAR_CONFIG) delete-deps
        rm -rf dev

dialyze-init:
        dialyzer --build_plt --apps erts kernel stdlib mnesia crypto public_key snmp reltool
        dialyzer --add_to_plt --plt ~/.dialyzer_plt --output_plt $(APP_NAME).plt -c .
        dialyzer -c ebin -Wunmatched_returns -Werror_handling -Wrace_conditions -Wunderspecs

dialyze: compile
        dialyzer --check_plt --plt $(APP_NAME).plt -c .
        dialyzer -c ebin

rel や dialyzer 周りは後ほど説明する。基本的には compile と get-deps がメインとなる。get-deps は依存関係の解決、compile はコンパイルと xref を呼び出す。

xref はクロスリファレンスで「存在しない関数」を呼び出したとき教えてくれる。

watchdog

url:https://pypi.python.org/pypi/watchdog

Python のライブラリだが、簡単に言えば「ファイルが更新されたら」している処理を行ってくれる。

$ watchmedo shell-command --patterns="*.erl;*.hrl" --recursive --wait --command="rebar compile xref eunit skip_deps=true" src include test

上記のように設定しておけば毎回コンパイルとテストが走る。

OMake の -P と似たような機能だ。

ライブラリ選定(Web 編)

Web サーバーライブラリ

まず Web アプリの場合は Cowboy を選択するのが無難だ。

ただしテンプレートも含めた開発となると難しい、あくまで API サーバを開発する前提が良いだろう。

HTTP クライアントライブラリ

HTTP クライアントは色々あるが Hackney が定番だ。プール機能も保持している上に、開発が活発だ。

cowboy_client という experimental なものもあるが、まずは Hackney を使っておくのが無難だろう。

JSON ライブラリ

そうなるとシリアライズする JSON ライブラリが重要になってくる。

日本後を扱うか、扱わないかで変わるが、基本的には jsxjsonx の二択になる。

jsx は日本後の取り扱いが簡単なので、まずは jsx で開発して行き、将来的に速度が必要になったら jsonx に変えて行くのが良いだろう。

ちなみに jsx は pure Erlang で jsonx は NIF (C 拡張) だ。

データベースライブラリ

メジャーなモノ以外はあまりないので自作することをお勧めする

テンプレートライブラリ

Erlang では頑張らないで素直に JSON を返しましょう ...

ライブラリ設定(その他)

リローダー

reloader と sync の二つがある。シンプルな reloader を好んで使っている。

コンパイルをすることで自動で読み込んでくれる機能だ。

$ erl -s reloader

これを使う事でわざわざ c(spam). という感じで再コンパイルする必要は無い。

Dialyzer

Dialyzer は静的解析ツールである。導入時にコストがかかることもあるのだが是非導入するべきだ。

導入編

Erlang/OTP で製品開発を行う際に一番の障壁となるのが「導入」だ。

「開発言語が使える人が居ない」などの理由で断られることがある。

ちなみに、これは至極まっとうな意見だと考えている。

方向

そもそも Erlang/OTP をネットワークサーバを書く用途以外で使うので無ければやめるべきだ。

ウェブアプリであれば、余地はあるかもしれない。ただ API サーバに限定すべき。

ウェブアプリでも JS 側でテンプレートを持ったりと昨今の JS 側の充実を考えると、 HTTP API サーバとしての活躍の場は徐々に広がってきているようだ。

Golang との比較

実は並列をメインとしている場合は、ほとんどの場合で Golang で書いた方がよい可能性が高い。

そもそもネットワークサーバではなく何かしらのツールを作ろうとしているのではないだろうか。

まずは社内で Golang と Erlang/OTP の比較をするべきだ。 本当に Erlang/OTP である「必要があるのか?」という事は大きなポイントだろう。

Erlang/OTP はネットワークサーバの DSL だと思って良い。 そのため得意では無い場面で使う場合はかなりのリスクがある。

さらにライブラリも 1 から開発する必要性も出てきたりする。

ライブラリ開発が難しい場合はそもそも Erlang/OTP などの人口が少ない言語を選択するのは懸命ではない。

アピール

もしそれでも開発したい場合は、アピールが必要になる可能性が高い。

主に、実績を聞かれると思う。そのときは以下のように答えれば良い。

有名どころはこの辺か。WhatsApp を知らない人はそうそういないだろう。もし居たとしたら 4.5 億ユーザがいる LINE ですと紹介すればいい。

上司がもしゲーム好きなら League of Legends のユーザ 7500 万人のチャットを支えていますよ。秒間 11000 メッセージを処理しています、というのもいいだろう。

これで落ちない場合は、基本的には勝手に実装して「とりあえずプロトタイプを Erlang/OTP で作ってしまいました」が良いだろう。

それがソースコードが比較的短く、性能が出るのであれば説得材料になり得る。

スケールアップ

もはや AWS が存在しているためスケールアウトが容易に出来る時代が来てしまった。ボトルネックはデータベースというパターンが多い。

しかし、今後は費用節約のためにスケールアップが求められる可能性がある。

前述した WhatsApp は数百台のサーバで 4.5 億ユーザを支え、秒間 7000 万リクエストを捌いているとのことだ。

今後、Erlang/OTP は スケールアップ という目的で使われることは多いかも知れない。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment