初心者の学習するには、分散 - 特使プロキシXDSサーバが動的に少し経験を使用するように設定します

要約特使プロキシの動的APIを使用します

特使プロキシおよび他のL4 / L7は、逆方向の最大の違いは、一次ツール支持動的構成することである無視します。およそのアーキテクチャ特使初めて目に

これは単に、図から理解することができる。特定のクラスタへの転送、処理後にフィルタ/ルータを介して、外部要求を受信し、そしてためのリスナーが担います。リスナー、ルータ、クラスタとホストアドレスが動的に構成されており、それがXディスカバリーサービスと呼ばれるサービスの構成データは、XDSと呼ばれます。

この記事では、XDSサーバーの更新ロジックを記述する方法について説明します。

GRPCサービスを通じて更新特使Porxy XDSサービスデータは、すべてのプロト・ファイルが参照できhttps://github.com/envoyproxy/envoy/tree/master/api/envoy/api/v2をユーザーは、ファイル自体プロトに対応GRPC言語コードファイルを生成することができます。あなたが叶うするgolangを使用している場合は、特使は、ここでGRPCコンパイルされたコード、アドレスを提供していますhttps://github.com/envoyproxy/go-control-plane/tree/master/envoy/api/v2

各XDSサービスは2つのGRPCサービスを提供しています、StreamDeltaStreamこれは、データの全額更新するために使用されるDelta増分データを更新するために使用します。RDSサービス下記の例として、XDSサービスを実装する方法を確認してください。

RDS Serviceこれは、すべて提供することがRoute簡略化され、通常の後、情報をRoute以下のように設定は次のとおりです。

# 完整的Route API定义参考 https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/rds.proto#envoy-api-msg-routeconfiguration

                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: local_service
                      domains: ["*"]
                      require_tls: NONE
                      routes:
                        - match:
                            prefix: "/MyService"
                          route: { cluster: my-grpc-svc_cluster }

上記構成セマンティクス:パスプレフィックスを受信する/MyService要求は、この要求に転送された後my-grpc-svc_clustermy-grpc-svc_clusterSTATIC型であってもよいアップストリーム情報の後端を表しCDS Service動的に提供されます)

RDS Service動的意味役割を生成することは上記の構成と同様です。まず見て、比較的単純なStreamRoutes方法。

次のようにGRPC記述ファイル、この関数が定義されています。

service RouteDiscoveryService {
  rpc StreamRoutes(stream DiscoveryRequest) returns (stream DiscoveryResponse) {
  }

  rpc DeltaRoutes(stream DeltaDiscoveryRequest) returns (stream DeltaDiscoveryResponse) {
  }

  rpc FetchRoutes(DiscoveryRequest) returns (DiscoveryResponse) {
    option (google.api.http) = {
      post: "/v2/discovery:routes"
      body: "*"
    };
  }
}

戻り値からわかるようにStreamRoutes、ストリーム関数をある、RDSは、このプッシュ特使を通じてリアルタイムにデータをストリーミングすることができます。だから、大体実装モデルは、以下のようなものです:

func (r rds) StreamRoutes(ls envoy_api_v2.RouteDiscoveryService_StreamRoutesServer) error {
    for{
        select{
            case x <- c>:
                ls.Send(xxx)
        }

    }
}

Send受け入れる関数DiscoveryResponseポインタを、このDiscoveryResponse定義の動的構造によっては自明です。特定の種類のデータは、typeUrl属性を決定しました。具体的なRouteことは、typeURL「type.googleapis.com/envoy.api.v2.RouteConfiguration」である。(タイプ説明参照https://www.envoyproxy.io/docs/envoy/latest/api-docs/xds_protocol.htmlを?タイプ=#%20urlハイライト資源タイプ

データでResource保存します。

Resourceある[]*any.Anyタイプは、その白色汎用インタフェース{}です。だから、作成any.Any特定のデータ型(「type.googleapis.com/envoy.api.v2.RouteConfiguration」)時間を指定する必要が。dataそれは結果であるProtoMessageバイナリエンコードされたデータ。だから、any.Anyは、次のようになります作成します。


            data, err := proto.Marshal(xxxx)
            if err != nil {
                logrus.Errorf("Marshal Error. %s", err)
                continue
            }

            any :=  &any.Any{
                TypeUrl: "type.googleapis.com/envoy.api.v2.Cluster",
                Value:   data,
            })

xxxxRDSであること、データをルーティングの特使に復帰することが必要ですRouteConfigurationそれを構築する方法で見てみましょうRouteConfigurationAPIの定義には、いくつかのデータ項目を失う(項目は、プロト負けキャリブレーションプロファイルにより取得し、しかしとして直接APIドキュメントを参照してくださいではないことにします)。我々はルートシンプルな構成の開口部を達成したいとし、それはRouteConfigurationこのように定義する必要があります。

      r:=&envoy_api_v2.RouteConfiguration{
            Name: "local_route",
            VirtualHosts: []*route.VirtualHost{
                &route.VirtualHost{
                    Name: "local_service",
                    Domains: []string{
                        "*",
                    },
                    Routes: []*route.Route{
                        &route.Route{
                            Match: &route.RouteMatch{
                                PathSpecifier: &route.RouteMatch_Prefix{Prefix: "/MyService"},
                            },
                            Action: &route.Route_Route{Route: &route.RouteAction{
                                ClusterSpecifier: &route.RouteAction_Cluster{Cluster: "my-grpc-svc_cluster"},
                            }},
                        },
                    },
                },
            },
        },

二つの場所に注意してください。

  1. 名前: "local_route"。RouteConfig名の名前は、ここではリスナーと一貫性の中で定義する必要があります。ない場合は、リスナーがこのルート設定をロードしません(つまり、これは、主キーに関連付けられている当事者の名前です)
  2. クラスタ名が一致している必要があります。ない場合は、後続の要求は、上流を転送する場合も同様に、それは検出されません

これらのステップの後、約完全なRoute DiscoveryResponse定義は完了です。そして、あなたの後に送信を呼び出すことによって特使に送信することができます。

しかし、物事は終わりませんでした今回は、オープニングと述べStream、同期全額をDelta同期増分を。もう少し詳しくは、中StreamRoutesであらゆるニーズ輸送現在のルートの設定だけでなく、すべてのデータ変更が発生していた個人は、多くの問題のため、このアプローチは、データ編成を感じ。が、それは本当に特使データ更新非常に便利(データの全額たびに、マージをしません)。何かをしようとしているユーザーを確認するために、常に時間のかかるものをマージし、特使は、ユーザーが実行できるようにすることを決めました。

だから我々は調整する必要がStreamRoutes実装モデルを:

func (r rds) StreamRoutes(ls envoy_api_v2.RouteDiscoveryService_StreamRoutesServer) error {
    for{
        select{
            case x <- c>:
                // x表示变动的数据
                n := merge(x) //对x进行merge操作,返回当前最新全量数据n

                var srvRoute []*route.Route
                for _, d := range n{
                    srvRoute = append(srvRoute, &route.Route{
                                        Match: &route.RouteMatch{
                                            PathSpecifier: &route.RouteMatch_Prefix{Prefix: xxxx},
                                        },
                                        Action: &route.Route_Route{Route: &route.RouteAction{
                                            ClusterSpecifier: &route.RouteAction_Cluster{Cluster: xxxx},
                                        }},
                                    })
                }

                rc := []*envoy_api_v2.RouteConfiguration{
                    &envoy_api_v2.RouteConfiguration{
                        Name: "local_route",
                        VirtualHosts: []*route.VirtualHost{
                            &route.VirtualHost{
                                Name: "local_service",
                                Domains: []string{
                                    "*",
                                },
                                Routes: srvRoute,
                            },
                        },
                    },
                }

                var resource []*any.Any

                for _, rca := range rc {
                    data, err := proto.Marshal(rca)
                    if err != nil {
                        return err
                    }

                    resource = append(resource, &any.Any{
                        TypeUrl: "type.googleapis.com/envoy.api.v2.RouteConfiguration",
                        Value:   data,
                    })
                }


                ls.Send(&envoy_api_v2.DiscoveryResponse{
                        VersionInfo: xxx,
                        Resources:   resource,
                        Canary:      false,
                        TypeUrl:     "type.googleapis.com/envoy.api.v2.RouteConfiguration",
                        Nonce:       time.Now().String(),
                    })
        }

    }
}

調整後、それぞれがルート特使最新のデータに戻ります。上記モデルは、単一の特使インスタンスの場合を考慮し、マルチインスタンスを考慮していません。マルチインスタンスリンクするとRDS Service、Cから得られたデータは、すべての特使インスタンスデータが一貫していることができない保証非冪等のイベント、となります。

達成StreamRoutes外観を実現する方法を、後にDeltaRoutes

Deltaデルタは、基準ストリームであり、それはプロトタイプを機能しなければならない、という観点から、関数プロトタイプのデータを同期させるために使用されるStreamRoutes類似。あなたがそう思うなら、あなたは間違っています

Deltaのみ転送データへストリーム(推測が長い接続を維持するためにデータ伝送効率を向上させ、かつないことです)。各転送が完了すると、特使は、リンクを切断するためのイニシアチブを取るでしょう。言い換えれば、特使の呼び出しがタイムアウトしているDeltaRoutes差分更新データを取得しますあなたが続く場合はstream、ライト・ロジックへの実装モデルを、あなたは時間をかけて、このストリームが不可解になることがありますclosed状態。その理由は、イベントに特使を受け取った後、ストリームをシャットダウンするためのイニシアチブをとるということです。

あなたが使用したいのであればDeltaモードを、それが(この時期の呼び出しがあるので)特使は、リアルタイムデータの変化に応答しない保証するものではありません。あなたが使用している場合やStreamモードを、ユーザーが独自のデータの正確性を維持するために(マージは非常に複雑である場合には、精度が低下します)が必要です。

だから、選択StreamまたはDeltaユーザーのための問題があります。

おすすめ

転載: www.cnblogs.com/vikings-blog/p/11993864.html