Muduo BufferとGoogle protobuf

5396 ワード

Muduo Buffer実現構想

  • は、まず、著者らが与えた図で説明する.bufferの読み取りおよび書き込みを制御するために、2つの下付きrederIndexおよびwriterIndexが見られる.
        +-------------------+------------------+------------------+
        | prependable bytes |  readable bytes  |  writable bytes  |
        |                   |     (CONTENT)    |                  |
        +-------------------+------------------+------------------+
        |                   |                  |                  |
        0      <=      readerIndex   <=   writerIndex    <=     size
    
  • buffer内部データ全体がvectorで格納され、ネットワークメッセージの一般的なフォーマットに従って、前に8バイトの空間が予約されており、メッセージ長フィールドの挿入が容易であり、空間全体が8+1024に初期化されている.
  • ソケットからデータを読み取る量が大きく、writerIndexがsizeに達すると、2つの状況を考慮する必要があります.readerIndexの前には十分なスペースがあります.この場合、既存のデータを前に移動し、後ろにスペースを空けるだけでいいです.現在のbufferが足りない場合はvectorのresizeを呼び出す必要があります.

  • protobufを使用してメッセージをシーケンス化


    1.protobufの概要


    protobufは全称google protocal bufferであり、構造化データをシーケンス化と逆シーケンス化する方法であり、googleのオープンソースライブラリであり、現在はC++、Java、Pythonの3言語のAPIを提供している.
    protobufの簡単な使い方は以下の通りです.
  • protoファイルを作成し、muduoなどのメッセージフォーマットを与える.query.proto;
  • protoc--cpp_を使用outコンパイルは、対応するC++バージョンのヘッダファイルとを生成する.ccファイル;
  • はプログラムでメッセージを使用するが、ここではリンクに-lprotobufを付けることに注意する.

  • protobufは、プログラムの実行時に取得したメッセージクラス名情報に基づいて、プロトタイプモードを用いて実装されるメッセージオブジェクトを動的に生成する反射メカニズムを実現することに重点を置く必要がある.

    2.プログラム全体のアーキテクチャ設計


    現在、クライアントとサーバの通信を容易にするための3つの設計戦略を漸進的に学習しています.今まとめます.

    2.1 bufferの使用


    これは、サーバとTCP接続の間にバッファBufferを追加する最も基本的な戦略であり、以下に示すように、接続中にデータが読み取り可能である場合、まずBufferに読み出され、Server(Client)はTCP Connectionを直接操作するのではなく、対応するBufferから直接データを読み出す.一方,サーバ(Client)が対側にデータを書き込む場合は,まずBufferに書き,Bufferはデータの送信を担当する.
    Bufferを使用することは、read、writeなどのPosixのAPIがブロックされているため、サーバが直接操作すると、非ブロックIO全体の目的は実現できません.したがって、バッファメカニズムが追加され、現在のsocketが読み取り可能または書き込み可能であるかどうかを管理することなく、サーバ(Client)が読み出しまたは書き込み時にバッファに対して直接動作することを保証することができる.
        TCP_Connection <=========> Buffer  <=========>Server(Client)                                 
    

    2.2 buffer+codecの使用


    Bufferを使用すると、長い接続でバッファから読み出されたデータがどのように分離されるかによって、粘着問題が発生するという問題が発生します.これは、データをパッケージ化して送信するたびに、エンドツーエンドがそのままパッケージ化できることを保証するパッケージ化とパケット化ポリシーを設計する必要があります.ここでは、メッセージの境界(r)を自分で定義したり、メッセージに長さのヘッダを追加したりする方法がたくさんあります.muduo著者(@chenshuo)は,パケットヘッダに長さ情報を付加するパケット分割ポリシーを採用した.これにより、サーバがClientにメッセージを送信しようとすると、codec(コーデック)が自動的にメッセージに長さ情報を付加してbufferに書き込み、逆にbufferから読み取ったメッセージは、ヘッダ長情報を読み出してコンテンツフィールドを上位層に送信する.
    このときの仕組みはこうです.メッセージのさらなる処理はCodecが担当し,その後Bufferに送信する.
    TCP_Connection <=========> Buffer  <=========> Codec <=========> Server(Client)
    

    2.3 buffer+protobuf codecの使用


    需要はプログラム改善の唯一の原動力である.上記のアーキテクチャに対して、文字列などの非構造化データを送信することは完全に可能ですが、構造化された情報を送信するには、次のようにします.
    srtuct student{
        string name,
        int No,
        string sex
    };
    

    このとき、メッセージはどのようにパッケージ化されますか.前に紹介したように、googleは私たちにprotobufを提供して、それはネット通信の中で比較的によく使われて、主に構造化のメッセージをシーケンス化するために使用して、メッセージの構造を定義するだけで、使用することができて、しかも同時に異なるタイプのメッセージを定義することができます.これにより、オープンソースのAPIを使用してメッセージをシーケンス化し、Bufferに書き込むことができます.これにより、構造化されたメッセージを処理するタスクはProtobuf_によって行われます.Codecが完了し、Buffer処理に渡されます.ここのProtobuf_Dispatcherは、異なるメッセージが異なる処理方法をカスタマイズしているため、主に異なるタイプのメッセージを配布するために使用されます.
    TCP_Connection <===> Buffer  <===> Protobuf_Codec <===> Protobuf_Dispatcher <===> Server(Client)