この記事は、Elixir Advent Calendar 2023その4 の1日目です
piacere です、ご覧いただいてありがとございます ![]()
Elixirプロセス間通信/分散/並行の方式が23種類もあるってご存じですか?
2023年時点では18種類 でしたが、そこからの2年で更に5つ、増えました
新し目のフィーチャは動画が充実しており、連動した新たな実践コラムや Elixir実践入門 のような書籍も増えていますので、2023年版よりも分かりやすくなっているかと思います
なお、下記の皆さまの実践コラムをリンクさせていただきました(ありがとございます) ![]()
@kikuyuta さん
@pojiro さん
@twinbee さん
@32hero さん
@RyoWakabayashi さん
@koyo-miyamura さん
@mokichi さん
@mnishiguchi さん
@GeekMasahiro さん
@MzRyuKa さん
@nako_sleep_9h さん
@Yoosuke さん
@t-yamanashi さん
@myasu さん
@B_tanuki さん
@nanbut14 さん
@zacky1972 さん
@ekzemplaro さん
@Shintaro_Hosoai さん
@mito_mito さん
@hisaway さん
Elixirアドベントカレンダー、応援お願いします
今年もやっています
① Stream
遅延リスト処理を実行する Stream は、プロセス単位の分離/分散では無いものの、並行処理の最もシンプルな例です
from @GeekMasahiro さん
from @kikuyuta さん
② spawn/send/receive
spawnシリーズ(関数を定義しつつプロセスとして起動、名前付き関数をプロセスとして起動、親プロセスとリンクするプロセスを起動 など)によるプロセス起動と、プロセス間でメッセージパッシングするsend/receiveは、並行/分散の最小単位です
from @MzRyuKa さん
from @nako_sleep_9h さん
from @Yoosuke さん
from @piacerex
③ Parallel Map
リストの各要素に対し、上記したspawn/sendでマルチコア並列化し、各々をreceiveで受け取るよう非同期化したものがParallel Mapです
from @RyoWakabayashi さん
④ Task
上記spawn/send/receiveのイディオムを、async/awaitによるシンプルなワーカープロセスに置き換え、バックグラウンド実行や非同期処理に特化させたものが Task です
from @t-yamanashi さん
from @pojiro さん
⑤ GenServer
上記Taskに、状態を保持できるようサーバープロセス化したものが GenServer です ※正確には、GenSeverから状態保持をオミットして作られたものがTaskです
同期処理(handle_call)/非同期処理(handle_cast)を選択できます
from @B_tanuki さん
from @piacerex
⑥ Agent
上記GenServerの状態を保持する部分を簡略化したものが Agent です
オブジェクト指向のメンバー変数のような使い方ができますが、実装としてはサーバープロセスに状態を保持しており、メッセージパッシングで状態操作をしています
from @B_tanuki さん
from @GeekMasahiro さん
from @kikuyuta さん
⑦ ETS/Registry
上記GenServerやAgentのような、1つの状態だけを保持するのでは無く、複数の状態をまとめて保持できるようにしたサーバープロセスが、インメモリDBである ETS や Registry です
いずれも、単一マシン上でのローカルアクセスしか出来ませんので、複数マシンでの共有をしたい場合は、後述するMnesiaやRedixを使う必要があります
from @nanbut14 さん
from @mnishiguchi さん
from @kikuyuta さん
⑧ GenStage
データ群をGenServerで作られたPubプロセス群に渡し、GenServerで作られたSubプロセス群に非同期でバケツリレーするPubSunが GenStage です
キューやバックプレッシャーを簡単に構築できます
from @twinbee さん
⑨ Flow
上記GenStageを応用して、マルチコア並列データ処理のパイプラインをシンプルに実現するのが Flow です
リスト処理するEnumとほとんと同じ書き味で、データ処理を並列化できます
from @twinbee さん
from @t-yamanashi さん
from @zacky1972 さん
⑩ Broadway
上記GenStageによるPubSub/キュー処理を抽象化しつつ、QoSや障害時ハンドリング、外部キュー連携(Amazon SQS、Google Cloud PubSub、Kafka、RabbitMQ、AMQP、Redis、Redis Stream、Splunk)を加えたものが Broadway です
from @RyoWakabayashi さん
⑪ Mnesia
上記ETSをマルチクラスタ分散化し、冗長化と自動復旧を可能としたのが Mnesia です
from @32hero さん
from @piacerex
⑫ Redix
インメモリDBであるRedisをElixirから使うアダプターが、Redix です
from @ekzemplaro さん
from @koyo-miyamura さん
⑬ Erlang分散(Node/global/EPMD/pg)
Node は、マルチクラスタ分散化されたElixirノードを制御するためのモジュールです
遠隔地にあるクラスタ上のプロセスとの通信を行う前のElixirノード間接続やその確認を行うのに使用します
マルチクラスタのプロセス名管理と分散ロックに global が使われます
分散化されたプロセスのグループ管理に pg が使われます
これら分散環境における名前解決を行うサーバープロセスがEPMDで、各クラスタごとに起動されます
from @piacerex
from @zacky1972 さん
⑭ libcluster
TCP/IP上でのマルチクラスタ分散化されたElixirノードを実現するのが libcluster です
下記ディスカバリ戦略を選択できます
- Gossip … スケーリングは固定
- EPMD … スケーリングは固定、Elixirネイティブ
- k8s … オートスケーリング、自己修復
- ECS統合 … オートスケーリング
- EC2統合 … オートスケーリング
from @piacerex
from @mokichi さん
from @mnishiguchi さん
⑮ dns_cluster
DNSをディスカバリ戦略としてlibclusterと同様のことを実現するのが dns_cluster てす
Phoniex 1.6から標準装備となりました
⑯ Rustler/Port/ErlPort/KafkaEx
いずれもElixirから他システムと連携するライブラリで、RustやPython等の他言語のシステムや、Kafka経由でのリモートシステム分散化を叶えます
from @Shintaro_Hosoai さん
from @pojiro さん
⑰ Protobuf/gRPC
ElixirでProtobuf/gRPCを行うことでも他システムと連携できますが、protobuf と grpc で実装できます
from @myasu さん
⑱ Channel
Channel は、WebSocketによって、何百万ものクライアントとの同時接続とメッセージ交換を叶えるPhoenix標準の仕組みです
HTTPベースのため高速では無いものの、複数クライアントで同一ステートを共有できる便利な分散システムです
⑲ LiveView
Channelを土台とし、Web SPAアーキテクチャを提供する LiveView は、複数フロントで1つの状態を共有/配信できるメカニズムでもあります
from @mito_mito さん
from @piacerex
⑳ LiveView stream
LiveView stream は、LiveViewで遅延処理を提供することで、大きなリストや絶え間なく更新されるデータ(連続データフィードやチャットアプリ等)を扱えるようにします
無限スクロール/遅延ロード/UIへのPubSub等の簡素化をもたらしつつ、パフォーマンス向上/メモリ使用量の劇的削減/フロントへの差分更新効率化も実現します
from @hisaway さん
from @mokichi さん
㉑ LiveView async
これまでTask等を使わなければ実現できなかったLiveViewのバックグラウンド/非同期処理をカンタンに書けるようにしたのが、LiveView async です
UIブロック解消によるUX向上とエラーハンドリング/タイムアウトの簡素化も実現します
from @t-yamanashi さん
from @piacerex
㉒ FLAME
FLAME は、Elixirの関数に対し、サーバーレス/FaaS同様のデマンド実行やスケーラビリティを実現するライブラリです
FLAMEは、サーバーレス/FaaSと比べ、既存システムのサーバーレス化/FaaS化のためのコード解体/再構成やマイクロ化が必要無く、サーバーレス/FaaSほど構成が複雑化しない点が大きなメリットです
from @kikuyuta さん
㉓ Livebookノード
Elixirは、iexやバイナリイメージ、escriptだけで無く、Web上開発環境の Livebook でも実行できますが、**Livebookは1つのElixirノードでもあり、分散クラスタのノードとして扱えます
つまり、通常コードの分散先にもできれば、Livebook/iex間での分散、Livebook間での分散等も可能ということです**
なおLivebook 0.13以降からは、Elixirノードとしてだけに限らず、REST API/GraphQL APIサーバーやExcelパーサーとしても構築可能となり、ますます分散環境として魅力的になっています
from @piacerex in ElixirImp#31「Elixirで作ったもの、何でもLT会」
終わりに
Elixirのバリエーションに富んだプロセス間通信/分散/並行の片鱗が伝わったら幸いです
ご興味ある方は、各イディオムで紹介した実践コラムを試して、その深淵を味わってください
なお今回、ご紹介したElixirプロセス間通信/分散/並行は、あなたのスキルからBright(輝き)とRight(正しさ)を引き出すプロダクト「Bright」でもスキル判定対象になっています

