web-dev-qa-db-ja.com

シリアライゼーション/デシリアライゼーションコンテキストを結合しない方法で、byte []をクラスインスタンスに解決する方法

シリアル化してソケットを介して送信するPOJOがあると考えてください。

希望するシリアル化戦略(JSON、XML、protobufなど)を使用して、実際のP​​OJOをbyte []に​​シリアル化し、それをソケット経由で送信できます。

Byte []はもう一方の端に到着しますが、この受信コンテキストでは、情報がどのクラスを表しているのかわかりません。そのため、どのPOJOクラスを構築して、そのフィールドへの入力を開始するのかをどのようにして知るのでしょうか。

受信するデータのタイプを想定できるコンテキスト内に複数のエンドポイント/ソケットを必要とせずにこれを実行したいと思います。同じソケットコンテキストでさまざまな種類のPOJOをすべて受け取りたい。

1つのアイデアは、これらのコンテキスト間でマッピングを共有し、型コードをクラス型にマッピングすることでした。その後、データを転送するためのユーザー定義のフレームを構築できます。

| 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 |
+----------------+---------------+---------------+----------------+
|                      TYPE CODE SECTION (32 bit int)             |
+----------------+---------------+---------------+----------------+
|                      PAYLOAD LENGTH SECTION (32 bit int)        |
+----------------+---------------+---------------+----------------+
|                          PAYLOAD SECTION                        |
+----------------+---------------+---------------+----------------+
|                          PAYLOAD CONTINUED....                  |
+----------------+---------------+---------------+----------------+
:                              .....                              :
+----------------+---------------+---------------+----------------+

シリアル化では、このタイプのコードをフレームに挿入し、シリアル化されたPOJOであるbyte []に​​追加して、このフレームを送信します。

もう一方の端では、フレームからこのタイプのコードを抽出して、共有マッピングで調べることができます。ヴォイラ!ソケットを介して送信されたクラスがわかったので、スムーズにデシリアライズできます

ただし、これらのコンテキストのすべてがこの共有マッピングと結合されているため、これは悪いようです。プロジェクトをマイクロサービス指向にしたい場合はどうなりますか?特に、ユースケースごとにマッピングが異なる可能性がある場合は、醜くなります。

これは人々が解決した問題であり、おそらく私はこの種のことの名前、または高レベルのデザインパターン/アイデアを知らないだけだと思いました。

誰かが何らかのコンテキストを提供できますか?この問題をすでに解決している解決策はすでに存在しますか?この種のものに名前はありますか?

2
tgabb

つまり、受信者がメッセージデータの処理方法を認識できるように、十分なメタデータを提供する必要があります。拡張性と疎結合をサポートするいくつかのアプローチが必要です。

メタデータがすべてのレシーバーがJava POJOクラスでインスタンス化が容易にできると想定している場合)であれば、クライアントとサーバーはすでにいくぶん密結合しています。

したがって、元のJavaクラスが送信者側にあったものについてのメタデータを説明するのではなく、メッセージ自体の性質、コンテンツ、およびフォーマットを説明することをお勧めします。おそらく1つを想定するのが最も簡単です。少なくともメッセージの構文を解析してフィールドとその内容を理解できるようにするため、両側でJSONまたはXMLを使用します。

さまざまなメッセージのドメイン指向の性質/目的の説明、および進化を可能にするバージョン管理(理想的には、クライアントとサーバーの独立したバージョン管理)に焦点を合わせます。これらのアプローチの一部では、たとえば、「理解する必要がある」と説明されているフィールドが表示されます。一方、新しく追加された他のフィールドは、理解できない場合は無視しても問題ありません。

スキーマ は、ここで使用するのに適しています。これらは、あるタイプの正当なメッセージを形成するものを説明する方法と、メッセージ内にその説明をエンコードする方法を提供します。さまざまな種類のメッセージは、独自のスキーマを持つか、追加のフィールド情報でいくつかの一般的なスキーマを増強します。


プロトコルバッファーは、何をしているのかがわかっていて、高速でシンプルであり、組み込みの柔軟性の多くを必要としない場合に適しています。 wikipedia から:

通常、メッセージはコンパクトで、前方互換性と後方互換性のあるバイナリワイヤ形式にシリアル化されますが、自己記述的ではありません(つまり、外部仕様がないと、フィールドの名前、意味、または完全なデータ型を知る方法はありません。 )。このような外部仕様(スキーマ)をプロトコルバッファファイルに含めたり参照したりするための定義された方法はありません。正式にサポートされている実装にはASCIIシリアル化形式が含まれますが、この形式は(自己記述的ではありますが)前方互換性動作と後方互換性動作を失うため、デバッグ以外のアプリケーションには適していません。

もちろん、スキーマに名前を付けたり識別したりするために独自の文字列またはID番号を含めることができますが、今ではカスタムスキーマシステムを発明しており、遭遇する多くの落とし穴があるため、既存のものを使用する方が良い場合があります。

5
Erik Eidt

通信の基本的な基礎は、送信者が受信者が望ましい状態に到達することを望んでいるということです(そうでなければ、なぜ送信者は気になりますか?)。

これを実現するために、送信者は、正常に動作する受信者に望ましい結果をもたらすメッセージを送信する必要があります(とんでもないまたは破壊的な受信者は、とにかく推論できません...)。

すぐに、これには送信者と受信者の間の何らかの形式の合意が必要です。送信者の目標は達成可能である必要があります。 (送信者である人の帽子がコミュニケーションで動き回る場合、参加者を着ている各送信者の帽子は、彼らの目標を合理的に達成することができる必要があります)。


だから問題はあなたが達成したい目標は何ですか?

データを記述したい場合、友達はJSON、YAML、XMLです。それらを使用するか、それらからインスピレーションを得ます。それらはいくつかのプリミティブ型を定義し、それらをより複雑な構造に組み合わせるメカニズムを提供します。これにより、構造について事前に合意する必要なく、データの任意の配置を渡すことができます。データ自体はその形式を自己記述します。欠点は、クライアントでメッセージの処理方法を理解することですが、すぐにはわかりません。

特定のメッセージについて説明したい場合は、PNGなどのスタイル言語をブロックしてください(画像フォーマットははい、仕様を確認してください)。BitTorrentはあなたの友人です。各ブロックには、合計ブロックサイズのヘッダー、潜在的にいくつかの管理フラグ、およびタイプ識別子があります。これにより、無関係/判読不能の場合にメッセージをスキップでき、理解されたメッセージを安全にデシリアライズできます。通信が合理化され、メッセージへの反応を非常に迅速に行うことができるため、これはレイテンシにとって優れています。欠点は、メッセージを事前に合意する必要があることです。これらのメッセージの1つに(JSONのような)データのみを送信させることで、これを回避できます。

拡張可能な言語が必要な場合は、FTP、VT(仮想端末)、Telnetワイヤプロトコルをご覧ください。それらには、どの拡張機能が利用可能で、どの拡張機能が優先されるかをネゴシエートし、それらの拡張機能を有効にするための特別な種類のメタメッセージがあります。これは一種の中間点を提供します。双方は合意に達する必要がありますが、メッセージの異なるセットに同意することができ、通信全体でそれらのメッセージを有効/無効にすることを選択できます。これにより、新しいメッセージセットを後で作成できるようになり、両側で実装された場合にのみ(おそらく)使用されます。

3
Kain0_0

デフォルトで明確化が必要なデザインですが、特別な理由がない限り壊れていると考えます。今、これらのオブジェクトは完全に直交していますか、それとも多形ですか?ポリモーフとは、次のような基本クラスがあることを意味します

class eventbase {
     string sender {get; set; }
     DateTime time {get; set; }
     string type {get; set; }
}

class usernamechangedevent: eventbase {
     string name {get; set; } 
}

このシナリオでは、多くの場合、基本型に逆シリアル化し、実際の型を読み取ってから、実際の型に逆シリアル化できます。参照: プロトコルバッファのポリモーフィズム

私たち(開発者)は、物事のタイプセーフを作成するために長く懸命に取り組みました。一般的には、そのままにしておくことをお勧めします。

1
Martin K