私は、アプリのユーザーにプラグインを作成させる方法を検討してきました。しかし、彼らにもっと多くのオプションを与えるために、私は多言語プラグインシステムを実装することにしました。
エンジニアリングの観点から、これを行うには複数の方法があります。
私が考えた1つの方法は、Jupyterカーネルを使用することでした。それぞれのインタープリターですでに実行されているイベントループ間で(IPCを介して)メッセージを送信します。解釈された/動的言語(少なくとも5つ)のみをサポートしたいので、実行時にロードしやすくなります。
私が見逃している一般的な方法はありますか?このようなアプリケーションを構築するにはどうすればよいですか?最も一般的な落とし穴を防ぐために何に注意する必要がありますか?
これはすべて、ある種のイベントループをサポートしながら機能する必要があります。ただし、pythonはとにかくそれを適切にサポートしていないため、スレッド化は必要ありません。
言語間のイベントループは完全に不可能というわけではありませんが、そのルートに行くと、苦痛の世界に陥ります。これだけで、自動生成された言語バインディングなどの一部のソリューションは除外されます。
2つのプログラミング言語を接続する唯一の簡単な方法は、IPCを使用することです。アプリケーションがプラグインをサブプロセスとして開始し、パイプを介して通信できるようにします。または、個別のプロセスが接続できるサーバーとしてアプリケーションを実装します。 IPCベースのソリューションの追加の利点:ほとんどのイベントループにより、読み取り可能なI/Oハンドルで簡単にトリガーできます。
これらのパイプを介して、任意の形式のメッセージを交換します。これは、単純な「1行に1つのJSONドキュメント」プロトコル、Protobufメッセージ、またはフルオンHTTPである可能性があります。これは、メッセージのシリアル化テクノロジとこれらのメッセージによって実装されるプロトコルの両方に関して、すべての参加者にとって実装が容易な設計を選択できる部分です。
プラグインプロトコルをどのように構成するかは、これらのアプリケーションが何をすることになっているのかによって異なります。例えば。プラグインは、一部のデータをマッサージするフィルターである可能性があります。次に、メインアプリケーションには次のようなコードがあります。
sendMessageToPlugin(data)
result = await readMessageFromPlugin()
したがって、これはプラグインとの効果的な同期通信ですが、アプリケーションをブロックすることはありません。プラグインは引き続きメッセージに順番に応答する必要がありますが、それは多くのワークロードにとって問題ではない可能性があります。
もう1つの単純なケースは、プラグインが単なるイベントコンシューマーである場合です。したがって、応答を受信せずにプラグインにメッセージを送信するだけです。しかし、これはいくつかの難しい質問を開きます:プラグインが現在消費できるよりも多くのイベントがある場合はどうなりますか?それらをどのようにバッファリングできますか?それらをバッファリングする必要がありますか?プラグインがクラッシュするとどうなりますか?
これらのより複雑なケースでは、プラグインとアプリケーションの間のブローカーとして機能する既存のメッセージキューを使用することが賢明な場合があります。
プラグインに小さく、シンプルで、明確に定義されたAPIを提供することは一般的に賢明です。これにより、プラグインが任意のデータを要求することができなくなります。代わりに、必要なデータを含むメッセージを定義します。共有データモデルが必要な場合は、外部データベースを使用するのが賢明かもしれません。外部データベースはアトミック更新を実行でき、データモデルの一貫性を保証するからです。その場合、メッセージには完全なデータではなく、データベースキーが含まれます。
設計が何らかの方向に進化すればするほど、SOAまたはマイクロサービスアプローチからのベストプラクティスを適用しやすくなることに注意してください。これらはすべて同じ問題、つまり複数のプロセス間の言語に依存しない連携に対処します。
また、これらのエンジニアリングの課題は解決できないわけではありませんが、それでも多くの努力が必要であることを指摘したいと思います。このプラグインシステムの開発コストを正当化する具体的なニーズがない限り、ホスト言語内にとどまる方がよい場合があります。ライブラリの統合は、IPCを扱うよりもはるかに簡単です。