この記事は、Elixir Advent Calendar 2023 シリーズ12 の21日目です
【本コラムは、15分で読めます】 ※各配下コラムをお読みいただく場合は各自次第で
piacere です、ご覧いただいてありがとございます
Elixirプロセス間通信/分散/並行の方式は19種類もあるってご存じでした?
今年は、Elixirによるマイクロサービス/エッジコンピューティングの土台となる機能(Umbrella、Node、Livebookなど)とその優位性を、LT/スライド/コラム等で解説しましたが、来年はElixirプロセス間通信/分散/並行の19種類ある方式それぞれを活用した実践例を示していこうと思っており、本コラムはその前触れやカンタンな紹介です
なお、下記の皆さまのコラム/動画などをリンクさせていただきました(ありがとございます)
@kikuyuta さん
@twinbee さん
@32hero さん
@pojiro さん
@RyoWakabayashi さん
@koyo-miyamura さん
@mokichi さん
@mnishiguchi さん
あと、このコラムが、面白かったり、役に立ったら、 をお願いします
① Stream
遅延リスト処理を実行する Streamモジュール は、プロセス単位の分離/分散では無いものの、並行処理の最もシンプルな例です
from @kikuyuta さん
② spawn/send/receive
spawnシリーズ(関数を定義しつつプロセスとして起動、名前付き関数をプロセスとして起動、親プロセスとリンクするプロセスを起動 など)によるプロセス起動と、プロセス間でメッセージパッシングするsend/receiveは、並行/分散の最小単位です
from @piacerex
③ Parallel Map
リストの各要素に対し、上記したspawnシリーズで処理を行い、それをreceiveで受け取るようにしたものがParallel Mapです
同期並行処理を叶えます
from @RyoWakabayashi さん
④ Task
上記spawnをワーカープロセス化に特化したものが Task です
spawn/send/receiveのイディオムを、async/awaitによるシンプルな同期並行処理/ワーカープロセス化に置き換えます
from @pojiro さん
⑤ GenServer
上記Taskのようなワーカープロセスに加え、状態を保持できるようにサーバープロセス化したものが GenServer です ※正確には、GenSeverから状態保持をオミットして作られたものがTaskです
同期処理(handle_call)/非同期処理(handle_cast)を選択できます
from @piacerex
⑥ Agent
上記GenServerのうち、状態を保持する部分を簡略化したものが Agent です
from @kikuyuta さん
⑦ ETS/Registry
上記GenServerやAgentのような、1つの状態だけを保持するのでは無く、複数の状態をまとめて保持できるようにしたサーバープロセスが、インメモリDBである ETS や Registry です
いずれも、単一マシン上でのローカルアクセスしか出来ませんので、複数マシンでの共有をしたい場合は、後述するMnesiaやRedixを使う必要があります
from @kikuyuta さん
⑧ GenStage
GenServerで作られたPubプロセス群に渡されたデータ/複数処理を、やはりGenServerで作られたSubプロセス群に非同期並行でバケツリレーするのが GenStage です
これにより、並行化されたPubSubが実現され、キューやバックプレッシャーを簡単に構築できます
from @twinbee さん
⑨ Flow
上記GenStageを応用して、マルチコア並列データ処理のパイプラインをシンプルに実現するのが Flow です
リスト処理するEnumとほとんと同じ書き味で、データ処理を並列処理化できます
from @twinbee さん
⑩ Broadway
上記GenStageを応用して、マルチコア並列データ処理をシンプルに実現するのが Broadway です
GenStageによるPubSub/キュー処理を抽象化しつつ、QoSや障害時ハンドリング、外部キュー連携(Amazon SQS、Google Cloud PubSub、Kafka、RabbitMQ、AMQP、Redis、Redis Stream、Splunk)を加えることが出来ます
from @RyoWakabayashi さん
⑪ Mnesia
上記ETSをマルチクラスタ分散化し、冗長化と自動復旧を可能としたのが Mnesia です
from @piacerex
from @32hero さん
⑫ Redix
Redix は、インメモリDBであるRedisをElixirから使うアダプターです
from @koyo-miyamura さん
⑬ Node/global/pg
Nodeモジュール は、マルチクラスタ分散化されたElixirノードを制御するためのモジュールです
遠隔地にあるプロセスとの通信を行う前のElixirノード間接続やその確認を行うのに使用します
マルチクラスタのプロセス名管理と分散ロックに globalモジュール が使われます
分散化されたプロセスのグループ管理に pgモジュール が使われます
from @piacerex
⑭ libcluster
TCP/IP上でのマルチクラスタ分散化されたElixirノードを実現するのが libcluster です
下記ディスカバリ戦略を選択できます
- Gossip … スケーリングは固定
- EPMD … スケーリングは固定、Elixirネイティブ
- k8s … オートスケーリング、自己修復
- ECS統合 … オートスケーリング
- EC2統合 … オートスケーリング
from @mokichi さん
from @mnishiguchi さん
⑮ dns_cluster
DNSをディスカバリ戦略としてlibclusterと同様のことを実現するのが dns_cluster です
⑯ ErlPort/KafkaEx/Protobufなど
いずれもElixirから他システムと連携するライブラリで、Python等の他言語のシステムや、Kafka/プロトコルバッファー経由でのリモートシステムとの分散化を叶えます
from @piacerex ※ライブラリ紹介のみ
⑰ FLAME
FLAME は、Elixirの関数に対し、サーバーレス/FaaS同様のデマンド実行やスケーラビリティを実現するライブラリです
FLAMEは、サーバーレス/FaaSと比べ、既存システムのサーバーレス化/FaaS化のためのコード解体/再構成やマイクロ化が必要無く、サーバーレス/FaaSほど構成が複雑化しない点が大きなメリットです(詳細は下記コラムにて)
from @kikuyuta さん
⑱ Channel/LiveView
Channel は、WebSocketによって、何百万ものクライアントとの同時接続とメッセージ交換を叶える仕組みで、複数クライアントで同一ステートを共有する分散システムです
Channelを土台とする LiveView も、Web SPAアーキテクチャであると同時に、複数クライアントで同一ステートを共有できます
from @piacerex
⑲ Livebookノード
現在のElixirは、コマンドランタイムだけで無く、Web上開発環境である Livebook 上で実行できるのですが、Livebookは1つのマシン/コマンドランタイムと同等に扱えるため、Livebook間やLivebook/コマンドランタイム間でのマルチクラスタ分散が可能です
Livebook 0.13では、REST API/GraphQL APIサーバーやExcelパーサーも構築可能となり、ますます分散環境として魅力的になり続けています
from @piacere in ElixirImp#31:Elixirで作ったもの、何でもLT会
終わりに
今回、ご紹介したElixirプロセス間通信/分散/並行は、過去/現在/未来のスキルからあなたのBright(輝き)とRight(正しさ)を引き出すプロダクト「Bright」でも、下図の通り、スキル判定対象になっています