まだ erlang の基礎もロクに勉強してないというのに、単に面白そうだから、という理由で並列プログラミングに手を出してみた。
HTTP get を複数の URL に対して並列で発行する。全体の構造は以下のようなもので。
- main
- manager プロセスを作成
- 引数で受けた URL のリストから、ひとつの URL ごとに worker プロセスを作成
- worker
- URL を HTTP GET して、結果を manager プロセスにメッセージ送信
- manager
- workerプロセスから受けたメッセージを出力
erlang、さわって二日目だけどかなり取っ付きやすい印象。
, で区切ったのが順番に実行されるし、printf デバッグもできるし。
Erlangは関数型だけど難しくない: みかログ には全面的に同意。
-module(cohttp). -compile(export_all). create_worker( Url, Manager ) -> spawn(?MODULE, worker, [ Url, Manager ]). worker( Url, Manager ) -> erlang:display(["starting worker", Url]), { Flag, Result } = http:request(Url), % HTTP get 発行 case Flag of ok -> { { _, Status, _ }, _, _ } = Result; % パターンマッチで Status 取り出し error -> Status = Result end, Manager ! [ Url, Status ]. % Manager にメッセージ送信 create_manager() -> spawn(?MODULE, manager, []). manager() -> receive % 受信したメッセージをパターンマッチ [ Url, Status ] -> io:format("~s is ~w~n", [ Url, Status ]), manager() % loop end. main( UrlList ) -> Manager = create_manager(), [ create_worker( Url, Manager ) || Url <- UrlList ].
実行結果。
Eshell V5.5.4 (abort with ^G) 1> c(cohttp). {ok,cohttp} 2> cohttp:main(["http://www.google.com", "http://www.yahoo.co.jp", "http://badhost/"]). ["starting worker","http://www.google.com"] ["starting worker","http://www.yahoo.co.jp"] ["starting worker","http://badhost/"] [<0.39.0>,<0.40.0>,<0.41.0>] 3> http://badhost/ is nxdomain http://www.google.com is 200 http://www.yahoo.co.jp is 200