1. ホーム
  2. architecture

[解決済み] Elixir/erlangはマイクロサービスアプローチのどこに位置づけられるのか?[クローズド]

2022-10-04 03:39:02

質問

最近、私は複数のマイクロサービスを協調してデプロイするために、docker composeを使った実験をしています。マイクロサービスが提供する多くの利点を理解し、それらを管理するための優れたツールセットがある今、マイクロサービスワゴンに飛び乗ることは非常に難しいことではないと思います。

しかし、私はElixirも試していて、それ自体が提供する利点にとても好感を持っています。コードを複数の非結合アプリケーションにパックすることを奨励し、ホットコードアップグレードをサポートすることを考えると、DockerとElixir(あるいはerlang)をどのように混ぜるのでしょうか?

例えば、dockerがdev-prod parityを提供してくれるから使いたいとして、elixirはそれにどうフィットするのでしょうか?dockerコンテナは不変であることを考えると、ホットコードによるアップグレードができなくなりますよね?ブルー/グリーンデプロイメントやカナリアリリースについてはどうでしょうか?

つまり、Elixirでマイクロサービスを書いて、他の言語で書かれたかのように使うことができます。ポリグロティズムはとにかくマイクロサービスの利点の1つですが、それではOTPプラットフォームを使う利点を完全に得ることはできません。

どのように解決するのですか?

これは非常にオープンな質問ですが、なぜElixir/Erlangが分散システムの開発に最適なプラットフォームなのかを説明したいと思います(マイクロサービスを扱っているかどうかは関係ありません)。

まず、いくつかの背景から始めましょう。Erlang VMとその標準ライブラリは、分散システムを構築するために前もって設計されており、これは本当によく現れています。私が知る限り、このユースケースのために前もって設計されたランタイムと生産現場で広く使われているVMはこれだけです。

アプリケーション

例えば、あなたはすでにアプリケーションについてほのめかしていますね。Erlang/Elixirでは、コードはアプリケーションの中にパッケージ化されています。

  1. はユニットとして起動・停止します。システムの起動と停止は、その中の全てのアプリケーションを起動することです。
  2. は統一されたディレクトリ構造と設定 API (これは XML ではありません!) を提供します。もしあなたが既にOTPアプリケーションで作業し設定したことがあるなら、他のどのアプリケーションでも作業する方法を知っているはずです。
  3. すべてのプロセス (プロセスとは、軽量な計算スレッドである VM プロセスを意味します) とその状態を含むアプリケーション監督ツリーを含みます。

この設計のインパクトは大きいです。Elixirの開発者は、アプリケーションを書くときに、より明示的なアプローチをとることになります。

  1. コードの開始と終了の方法
  2. アプリケーションを構成するプロセスは何か、したがってアプリケーションの状態は何か。
  3. クラッシュや何か問題が発生したときに、これらのプロセスがどのように反応し、影響を受けるか。

それだけでなく、この抽象化の周りのツールも素晴らしいです。Elixirがインストールされているなら、"iex"を開いて、次のようにタイプしてください。 :observer.start() . ライブシステムに関する情報やグラフが表示されるだけでなく、ランダムなプロセスを終了させ、そのメモリ使用量や状態などを確認することができます。以下は、Phoenix アプリケーションでこれを実行した例です。

ここでの違いは、アプリケーションとプロセスで 実稼働中のコードを推論するための抽象化機能 . 多くの言語がパッケージ、オブジェクト、モジュールを提供していますが、これは主にコードを整理するためのもので、ランタイムシステムへの反映はありません。クラス属性やシングルトンオブジェクトがあったとして、それを操作できるエンティティについてどのように推論することができますか?メモリリークやボトルネックがあった場合、その原因となっているエンティティをどのように見つけることができるでしょうか?

分散システムを動かしている人に聞けば、彼らはこのような洞察力を求めているはずです。

コミュニケーション

これらはすべて、本当に始まりに過ぎません。分散システムを構築する場合、通信プロトコルとデータシリアライザーを選択する必要があります。多くの人が HTTP と JSON を選択しますが、これは考えてみれば、実際には RPC 呼び出しであるものを実行するには非常に冗長で高価な組み合わせです。

Erlang/Elixirでは、通信プロトコルとシリアライゼーションメカニズムをすでに持っています。もし2つのマシンがお互いに通信したいのであれば、名前をつけて、同じ秘密を持っていることを確認するだけでよいのです。

JamieはErlang Factory 2015でこのことを話し、ゲームプラットフォームを構築するためにこれをどのように活用することができたかを話しました。 https://www.youtube.com/watch?v=_i6n-eWiVn4

HTTPとJSONを使いたいのであれば、それも問題ありませんし、PlugのようなライブラリやPhoenixのようなフレームワークが、ここでも生産性を保証してくれるでしょう。

マイクロサービス

これまで、私はマイクロサービスについて話してきませんでした。それは、この時点まで、それらが本当に重要でないからです。あなたはすでに、分離された非常に小さなプロセスを中心にシステムとノードを設計しています。お望みであれば、ナノサービスと呼んでください。

それだけでなく、それらはアプリケーションにパッケージ化されており、ユニットとして起動および停止できるエンティティとしてグループ化されています。アプリケーション A、B、C があり、それらを [A, B] + [C] または [A] + [B] + [C] としてデプロイしたい場合、その固有の設計により、そうすることにほとんど問題はないでしょう。あるいはさらに、マイクロサービスのデプロイの複雑さを前もってシステムに加えることを避けたいのであれば、それらをすべて同じノードにデプロイすればいいのです。

そして、結局のところ、もしあなたがErlang分散プロトコルを使ってこれらすべてを実行しているなら、異なるノードでそれらを実行することができますし、あなたがそれらを {:node@network, :name} の代わりに :name .

もっと言いたいことはあるのですが、この時点で納得していただけたでしょうか:)