プロトコル拡張-ユスケス

プロトコル拡張は,次のユ,スケ,スで使用できます。

  • メッセ、ジベ、スの負荷分散(mblb)
  • ストリ,ミング
  • ト,クン,ベ,スのロ,ド,バランシング
  • ロ,ド·バランシングの永続性
  • TCP接続ベ,スのロ,ドバランシング
  • コンテン·ベスのロド·バランシング
  • SSL
  • トラフィックを変更する
  • クラ▪▪アントまたはサ▪▪バへのトラフィックの発信元
  • 接続確立のデ,タを処理する

メッセ,ジ,ベ,スのロ,ド,バランシング

プロトコル拡張では,メッセージベース負荷分散(MBLB)がサポートされています.MBLB(メッセージベース負荷分散)は,Citrix ADCアプライアンス上の任意のプロトコルを解析し,1つのクライアント接続で受信したプロトコルメッセージを負荷分散します。MBLBは,クラアントTCPデタストリムを解析するユザコドによって実現されます。

TCPデータストリームは,クライアントとサーバーの動作のためにon_dataコールバックに渡されます。TCPデ,タストリ,ムは;Lua文字列APIに似たAPIを使用して,TCPデ,タストリ,ムを解析できます。

有用なAPIには,次のものがあります。

数据:len ()

数据:发现()

数据:字节()

数据:子()

数据:分裂()

TCPデータストリームがプロトコルメッセージに解析されると,ユーザーコードは,クライアント用のon_dataコールバックに渡されたコンテキストから利用可能な次のコンテキストにプロトコルメッセージを送信するだけで負荷分散を実現します。

ns。send () APIは,他の処理モジュ,ルにメッセ,ジを送信するために使用されます。送信先コンテキストに加えて、send API はイベント名とオプションのペイロードを引数として受け取ります。イベント名とビヘイビアのコールバック関数名には、1 対 1 の対応があります。イベントのコールバックは on_と呼ばれます 。コールバック名は小文字のみを使用します。

たとえば,TCPクライアントおよびサーバーのon_dataコールバックは,“数据”という名前のイベントのユーザー定義ハンドラーです。1回の送信コルでプロトコルメッセジ全体を送信するには,eomベントが使用されます。加工は,メッセージの終わりを表し,磅コンテキストのダウンストリームへのプロトコルメッセージの終わりを示します。したがって,このメッセ,ジの後に続くデ,タに対して新しいロ,ドバランシングの決定が行われます。

拡張コドは,on_dataベントでプロトコルメッセジ全体を受信しないことがあります。このような場合には,ctxt: hold () APIを使用してデ,タを保持することができます。保留APIは,TCPクライアントコンテキストとサーバコールバックコンテキストの両方で使用できます。“デ,タで保持”が呼び出されると,デ,タはコンテキストに格納されます。同じコンテキストでより多くのデータが受信されると,新しく受信したデータが以前に格納されたデータに追加され,on_dataコールバック関数が結合されたデータで再び呼び出されます。

注:使用される負荷分散方法は,負荷分散コンテキストに対応する負荷分散仮想サーバーの構成によって異なります。

次のコードスニペットは,发送APIを使用して解析されたプロトコルメッセージを送信する方法を示しています。

例:

客户端功能。On_data (ctxt, payload) -- --代码用于解析payload。数据进入协议消息来自这里-- --发送消息到lb ns.send(ctxt. send)。output, "EOM", {data = message}) end——客户端。On_data函数服务器。On_data (ctxt, payload) -- --代码用于解析payload。数据进入协议消息来自这里-- --发送消息到客户端ns.send(ctxt. send)。output, "EOM", {data = message}) end - server。on_data < !——NeedCopy >

ストリ,ミング

シナリオによっては,プロトコルメッセージ全体が収集されるまでTCPデータストリームを保持する必要がない場合があります。実際には,それが必要でない限り,それは助言されません。データを保持すると,Citrix ADCアプライアンスのメモリ使用量が増加し,多くの接続で不完全なプロトコルメッセージでCitrix ADCアプライアンスのメモリを使い果たすことにより,アプライアンスがDDoS攻撃を受けやすくなります。

ユーザーは、发送APIを使用して,拡張コールバックハンドラでTCPデータのストリーミングを実現できます。メッセ,ジ全体が収集されるまでデ,タを保持する代わりに,デ,タをチャンクで送信できます。DATA ` `ベントを使用してctxt。输出にデ,タを送信すると,部分的なプロトコルメッセ,ジが送信されます。これは,より多くのdata escベントが続くことができます。プロトコルメッセジの終わりをマクするには,eomベントを送信する必要があります。ロ,ドバランシングコンテキストは,最初に受信したデ,タに対してロ,ドバランシングの決定を行います。严メッセ,ジの受信後,新しいロ,ドバランシングの決定が行われます。

プロトコルメッセージデータをストリーミングするには,複数の数据イベントの後に加工イベントを送信します。連続する数据イベントと次の加工イベントは,シーケンスの最初の数据イベントのロードバランシングの決定によって選択された同じサーバー接続に送信されます。

クラ▪▪▪アントコンテキストに送信する場合,eom▪▪ベントとdata▪▪ベントは事実上同じです。これは,クライアントコンテキストのダウンストリームによる加工イベントに対する特別な処理がないためです。

ト,クン,ベ,スのロ,ド,バランシング

ネイティブでサポートされるプロトコルの場合,Citrix ADCアプライアンスは,π式を使用してトークンを作成するトークンベースの負荷分散方式をサポートします。拡張の場合,プロトコルは事前に知られていないため,pi式は使用できません。トークンベースの負荷分散では,USER_TOKEN負荷分散メソッドを使用するようにデフォルトの負荷分散仮想サーバーを設定し,USER_TOKENフィールドで送信APIを呼び出して拡張コードからトークン値を指定する必要があります。トークン値が送信APIから送信され,USER_TOKENロードバランシング方式がデフォルトのロードバランシング仮想サーバーで構成されている場合,トークンの値に基づいてハッシュを計算することによってロードバランシングの決定が行われます。トクン値の最大長は64バトです。

添加lb vserver v\_mqttlb USER\_TCP -lbMethod USER\_TOKEN

次の例のコ,ドスニペットは,送信APIを使用してlbト,クン値を送信します。

例:

——将消息发送给lb——user_token设置为基于clientID ns.send(ctxt. send)执行lb。output, "EOM", {data = message, user_token = token_info}) 

ロ,ド·バランシングの永続性

ロ,ドバランシングの永続性は,ト,クンベ,スのロ,ドバランシングと密接に関連しています。ユーザーは,永続性セッション値をプログラムで計算し,永続性を負荷分散するために使用できる必要があります。送信APIは,永続性パラメ,タを送信するために使用されます。負荷分散の永続性を使用するには,デフォルトの負荷分散仮想サーバーでUSERSESSION永続性タイプを設定し,user_sessionフィールドを指定して送信APIを呼び出して,拡張コードから永続性パラメータを指定する必要があります。永続性パラメタ値の最大長は64バトです。

カスタムプロトコルに複数のタイプの永続性が必要な場合は,ユーザー永続性タイプを定義して設定する必要があります。仮想サ,バの設定に使用されるパラメ,タの名前は,プロトコル実装者によって決定されます。パラメ,タの設定値は,拡張コ,ドでも使用できます。

次のCLIとコードスニペットは,ロードバランシングの永続性をサポートする送信APIの使用方法を示しています。mqtt。Luaのコ,ドリストのセクションにあるコ,ドリストでは, user_sessionフィ,ルドの使用方法も示しています。

永続性にいては,負荷分散仮想サバでUSERSESSION永続性タプを指定し,ns。发送APIからuser_session値を渡す必要があります。

添加lb vserver v\_mqttlb USER\_TCP -persistencetype USERSESSION

ペイロードでuser_sessionフィールドをclientIDに設定して,MQTTメッセージをロードバランサーに送信します。

例:

user_session也被设置为clientID(它将被用于持久化会话)output, " DATA ", {DATA = DATA, user_session = clientID}) 

TCP接続ベ,スのロ,ドバランシング

一部のプロトコルでは,mblbは必要ない場合があります。代わりに,tcp接続ベ,スの負荷分散が必要になる場合があります。たとえば,MQTTプロトコルはTCPストリームの最初の部分を解析して,負荷分散用のトークンを決定する必要があります。また,同じTCP接続上のすべてのMQTTメッセージは,同じサーバー接続に送信する必要があります。

TCP接続ベースのロードバランシングは,数据イベントのみで发送APIを使用し,加工を送信しないことで実現できます。このようにして,ダウンストリームの負荷分散コンテキストは,最初に受信したデータに基づいて負荷分散を決定し,その後のすべてのデータを負荷分散の決定によって選択された同じサーバー接続に送信します。

また,ユースケースによっては,ロードバランシングの決定後に拡張処理をバイパスする機能が必要になる場合があります。拡張呼び出しをバイパスすると,トラフィックが純粋にネイティブコードで処理されるため,パフォーマンスが向上します。バaapl .pipe()APIを使用して行うことができます。pipe () API拡張コ,ドを呼び出すと,入力コンテキストを出力コンテキストに接続できます。管()の呼び出しの後,入力コンテキストからのすべてのイベントが直接出力コンテキストに移動します。実際には,pipe()呼び出しが行われたモジュルはパプランから削除されます。

次のコードスニペットは,ストリーミングと管()APIを使用してモジュールをバイパスする方法を示しています。mqtt。Luaのコ,ドリストのセクションにあるコ,ドリストは,ストリーミングを行う方法と管()APIを使用して接続上の残りのトラフィックに対してモジュールをバイパスする方法も示しています。

例:

——发送到lb ns.send(ctxt. send)output, "DATA", {DATA = DATA, user_token = clientID})——将后续流量输送到lb -绕过客户端on_data处理程序ns.pipe(ctxt. pipe)。Input, ctext .output) 

コンテン·ベスのロド·バランシング

ネティブプロトコルの場合,プロトコル拡張のコンテンスッチングと同様の機能がサポトされます。この機能を使用すると,デフォルトのロードバランサーにデータを送信する代わりに,選択したロードバランサーにデータを送信できます。

プロトコル拡張のコンテンスッチング機能は,ctxt: lb_connect (< lbname >) APIを使用することによって実現されます。このAPIは,tcpクラaaplアントコンテキストで使用できます。拡張コードは,このAPIを使用して,すでに設定されている負荷分散仮想サーバーに対応する負荷分散コンテキストを取得できます。その後,取得した負荷分散コンテキストで送信APIを使用できます。

lbコンテキストはNULLになることがあります。

  • 仮想サ,バが存在しません
  • 仮想サバがユザプロトコルタプではありません
  • 仮想サバの状態がupではありません
  • 仮想サ,バは,負荷分散仮想サ,バではなく,ユ,ザ,の仮想サ,バです。

ターゲットの負荷分散仮想サーバーの使用中に削除すると,その負荷分散仮想サーバーに関連付けられているすべての接続がリセットされます。

次のコ,ドスニペットは,lb_connect () APIの使用方法を示しています。このコードは,Luaテーブルlb_mapを使用してクライアントIDを負荷分散仮想サーバー名(lbname)にマップし,lb_connect()を使用してlbnameの磅コンテキストを取得します。最後に,发送APIを使用してLBコンテキストに送信します。

local lb_map = {["client1*"] = "lb_1", ["client2*"] = "lb_2", ["client3*"] = "lb_3", ["client4*"] = "lb_4"}——将clientID映射到相应的LB vserver上,并为client_pattern, lbname in pairs(lb_map) do local match_idx = string。find(clientID, client_pattern) if (match_idx == 1) then lb_ctxt = ctxt:lb_connect(lbname) if (lb_ctxt == nil) then error("Failed to connect to LB vserver: " ..lbname) end break end end if (lb_ctxt == nil) then——如果lb context是NULL,用户可以引发一个错误或发送数据到默认lb error("Failed to map lb vserver for client: " ..clientID) end——将迄今为止的数据发送到lb ns。send(lb_ctxt, "DATA", {DATA = DATA} 

SSL

拡張機能を使用するプロトコルのSSLはネイティブプロトコルのSSLがサポートされる方法と同様の方法でサポートされます。カスタムプロトコルを作成するために同じ解析コードを使用して,TCPまたはSSLを介してプロトコルインスタンスを作成し,仮想サーバーを構成するために使用することができます。同様に,tcpまたはSSL経由でユザサビスを追加できます。

詳細にいては,MQTTのSSLオフロドの設定およびエンドエンド暗号化を使用したMQTTのSSLオフロ,ドの設定を参照してください

サ,バ,接続の多重化

場合によっては,クライアントは一度に1つの要求を送信し,最初の要求の応答がサーバーから受信された後に次の要求を送信します。この場合,サーバー接続は,応答がクライアントに送信された後,他のクライアント接続および同じ接続上の次のメッセージに再利用できます。他のクライアント接続によるサーバー接続の再利用を許可するには,サーバー側のコンテキストでctxt: reuse_server_connection () APIを使用する必要があります。

:このAPIは,Citrix ADC 12.1ビルド49.xx以降で使用できます。

トラフィックを変更する

要求または応答のデータを変更するには,高度なポリシーπ式を使用するネイティブの書き換え機能を使用する必要があります。拡張でπ式を使用できないため,次のAPIを使用してTCPストリームデータを変更できます。

Data:replace(offset, length, new_string) Data:insert(offset, new_string) Data:delete(offset, length) Data:gsub(pattern, replace [,n]))

次のコ,ドスニペットは,replace () APIの使用方法を示しています。

——得到的补偿模式,我们想要取代当地old_pattern =“repalace模式”old_pattern_length = old_pattern: len()当地pat_off pat_end =数据:找到(old_pattern)模式不存在如果(不是pat_off)那么goto send_data结束——如果我们想要修改的数据是不完全,然后,等待更多数据如果(不是pat_end)然后ctxt:保存(数据)数据= nil goto端数据:替换(pat_off old_pattern_length,“新模式”)::send_data: ns.send (ctxt。output, " EOM ", {data = data})::done::

次のコ,ドスニペットは,insert () APIの使用方法を示しています。

数据:插入(5、“图案要插入”)

次のコードスニペットは,いくつかのパターンの前または後に挿入したいときに,插入()APIの使用を示しています。

——获取模式的偏移量,在我们想要插入的模式之后或之前,local pattern = " pattern after/before which we need to insert " local pattern_length = pattern:len() local pat_off, pat_end = data:find(pattern)——模式不存在if (not pat_off) then goto send_data end——如果我们想要插入的模式之后不——完全存在,然后等待更多的数据如果(不是pat_end)那么ctxt:hold(data) data = nil goto done end——在模式数据之后插入数据:Insert (pat_end + 1, " pattern to Insert ")——在模式数据之前插入数据:Insert (pat_off, " pattern to Insert ")::send_data:: ns.send(ctxt. send)::send_data:: ns.send(ctxt. end)。output, " EOM ", {data = data})::done::

次のコ,ドスニペットは,delete () APIの使用方法を示しています。

——得到的补偿模式,我们要删除当地delete_pattern =“模式删除”delete_pattern_length = delete_pattern: len()当地pat_off pat_end =数据:找到(old_pattern)模式不存在如果(不是pat_off)那么goto send_data结束——如果我们想删除的数据是不完全,,然后等待更多数据如果(不是pat_end)然后ctxt:保存(数据)数据= nil goto端数据:删除(pat_off delete_pattern_length):: send_data: ns.send (ctxt。output, " EOM ", {data = data})::done::

次のコ,ドスニペットは,gsub()APIの使用を示しています。

——替换所有的实例模式与新的字符串数据:gsub(“老模式”,“新的字符串”)——取代“旧模式”的只有2实例数据:gsub(“老模式”,“新字符串”,2)——插入new_string之前“http”的所有实例数据:gsub(“输入数据”,“(http)”,“new_string % 1”),插入后new_string“http”的所有实例数据:gsub(“输入数据”,“(http)”,“% 1 new_string”)——插入new_string之前只有2“http”数据的实例:gsub(“输入数据”,“(http)”,“new_string % 1”,2)

:このAPIは,Citrix ADC 12.1ビルド50.xx以降で使用できます。

クラ▪▪アントまたはサ▪▪バへのトラフィックの発信元

ns。send () APIを使用して,拡張コードから生成されたデータをクライアントとバックエンドサーバーに送信できます。クライアントコンテキストからクライアントと直接応答を送受信するには,ctxt.clientをターゲットとして使用する必要があります。サーバーコンテキストからバックエンドサーバーと直接応答を送受信するには,ctxt.serverをターゲットとして使用する必要があります。ペロドのデタは,TCPストリムデタまたはLua文字列です。

接続でのトラフィック処理を停止するには,クライアントまたはサーバコンテキストからctxt:关闭()APIを使用できます。このAPIは,クラアント側の接続またはそれにリンクされているサバ接続を閉じます。

ctxt: close () APIを呼び出すと,拡張コードがクライアントとサーバー接続にTCP鳍パケットを送信します。この接続でクライアントまたはサーバーからより多くのデータが受信されると,アプライアンスは接続をリセットします。

次のコ,ドスニペットは,ctxt.clientとctxtの使用方法を示しています。クロ,ズ()api。

——如果输入数据包不是MQTT CONNECT类型,那么——向客户端发送一些错误响应。客户端功能。On_data (ctxt, payload)本地数据= payload。data local offset = 1 local msg_type = 0 local error_response = " Missing MQTT Connect packet. "" byte = data:byte(offset) msg_type = bit32. "rshift(字节,4)if (msg_type ~= 1) then——发送错误响应ns.send(ctxt. 4)客户端," DATA ", {DATA = error_response})——由于错误响应已经发送,所以现在关闭连接ctxt:close()结束

次のコ,ドスニペットは,ユ,ザ,が通常のトラフィックフロ,にデ,タを注入できる例を示しています。

——发送请求后,向服务器发送一些日志消息。客户端功能。On_data (ctxt, payload)本地数据= payload。数据本地log_message = "客户端id: " ..数据:子(3、7). ."用户名:" data:sub(9,15)——将我们从客户端获得的请求发送到后端服务器ns.send(ctxt. Send)。output, " DATA ", {DATA = DATA})发送请求后,还要发送日志消息ns.send(ctxt. send, {DATA = DATA})output, " DATA ", {DATA = log_message "})结束

次のコ,ドスニペットは,ctxt。to_server APIの使用方法を示しています。

—如果HTTP响应状态消息为“Not Found”,—则向服务器发送另一个请求。服务器功能。On_data (ctxt, payload)本地数据= payload。data local request " GET /default.html HTTP/1.1\r\n\r\n " ss local start, end = data:find(" Not Found ") if (start) then——发送另一个请求到服务器ns.send(ctxt. html)。server, " DATA ", {DATA = request})结束

:このAPIは,Citrix ADC 12.1ビルド50.xx以降で使用できます。

接続確立でのデ,タ処理

接続確立時にデタを送信したいユスケスがあるかもしれません(最終的なackを受信したとき)。たとえば,プロキシプロトコルでは,接続確立時にクライアントの送信元と宛先IPアドレスとポートをバックエンドサーバーに送信できます。この場合,client.init()コールバックハンドラを使用して,接続確立時にデータを送信することができます。

次のコ,ドスニペットは,客户端。Init()コ,ルバックの使用方法を示しています。

——在连接建立时向下一个处理上下文发送请求。函数client.init(ctxt)本地请求“代理TCP4”+ ctxt.client.ip.src。To_s + " " + ctx .client.ip.dst。to_s + " " + ctext .client.tcp.srcport + " " + ctext .client.tcp.dstport——将另一个请求发送到服务器ns.send(ctxt. Send)。output, " DATA ", {DATA = request})结束

:このAPIは,Citrix ADC 13.0ビルドxx.xx以降で使用できます。