プロトコル拡張 - ユースケース
-
メッセージベースの負荷分散 (MBLB)
-
ストリーミング
-
トークンベースの負荷分散
-
ロード・バランシング・パーシステンス
-
TCP 接続ベースのロードバランシング
-
コンテンツベースの負荷分散
-
SSL
-
トラフィックを変更
-
クライアントまたはサーバーへのトラフィックの発信
-
接続確立時のデータ処理
メッセージベースの負荷分散
data:len()
data:find()
data:byte()
data:sub()
data:split()
function client.on_data(ctxt, payload)
--
-- code to parse payload.data into protocol message comes here
--
-- sending the message to lb
ns.send(ctxt.output, "EOM", {data = message})
end -- client.on_data
function server.on_data(ctxt, payload)
--
-- code to parse payload.data into protocol message comes here
--
-- sending the message to client
ns.send(ctxt.output, "EOM", {data = message})
end -- server.on_data
ストリーミング
トークンベースの負荷分散
add lb vserver v\_mqttlb USER\_TCP –lbMethod USER\_TOKEN
-- send the message to lb
-- user_token is set to do LB based on clientID
ns.send(ctxt.output, "EOM", {data = message,
user_token = token_info})
ロード・バランシング・パーシステンス
add lb vserver v\_mqttlb USER\_TCP –persistencetype USERSESSION
-- send the data so far to lb
-- user_session is set to clientID as well (it will be used to persist session)
ns.send(ctxt.output, “DATA”, {data = data, user_session = clientID})
TCP 接続ベースのロードバランシング
-- send the data so far to lb
ns.send(ctxt.output, "DATA", {data = data,
user_token = clientID})
-- pipe the subsequent traffic to the lb - to bypass the client on_data handler
ns.pipe(ctxt.input, ctxt.output)
コンテンツベースの負荷分散
<lbname> この API は TCP クライアントコンテキストで使用できます。この API を使用すると、拡張コードは、すでに構成されている負荷分散仮想サーバーに対応する負荷分散コンテキストを取得できます。その後、取得した負荷分散コンテキストで送信 API を使用できます。
-
仮想サーバーは存在しません
-
仮想サーバーはユーザープロトコルタイプではありません
-
仮想サーバーの状態は UP ではありません
-
仮想サーバーはユーザー仮想サーバーであり、負荷分散仮想サーバーではありません
local lb_map = {
["client1*"] = "lb_1",
["client2*"] = "lb_2",
["client3*"] = "lb_3",
["client4*"] = "lb_4"
}
-- map the clientID to the corresponding LB vserver and connect to it
for 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
-- If lb context is NULL, the user can raise an error or send data to default LB
error("Failed to map LB vserver for client: " .. clientID)
end
-- send the data so far to lb
ns.send(lb_ctxt, "DATA", {data = data}
SSL
サーバー接続の多重化
トラフィックを変更
data:replace(offset, length, new_string)
data:insert(offset, new_string)
data:delete(offset, length)
data:gsub(pattern, replace [,n]))
-- Get the offset of the pattern, we want to replace
local old_pattern = “pattern to repalace”
local old_pattern_length = old_pattern:len()
local pat_off, pat_end = data:find(old_pattern)
-- pattern is not present
if (not pat_off) then
goto send_data
end
-- If the data we want to modify is not completely present, then
-- wait for more data
if (not pat_end) then
ctxt:hold(data)
data = nil
goto done
end
data:replace(pat_off, old_pattern_length, “new pattern”)
::send_data::
ns.send(ctxt.output, “EOM”, {data = data})
::done::
data:insert(5, “pattern to insert”)
-- Get the offset of the pattern, after or before which we want to insert
local pattern = “pattern after/before which we need to insert”
local pattern_length = pattern:len()
local pat_off, pat_end = data:find(pattern)
-- pattern is not present
if (not pat_off) then
goto send_data
end
-- If the pattern after which we want to insert is not
-- completely present, then wait for more data
if (not pat_end) then
ctxt:hold(data)
data = nil
goto done
end
-- Insert after the pattern
data:insert(pat_end + 1, “pattern to insert”)
-- Insert before the pattern
data:insert(pat_off, “pattern to insert”)
::send_data::
ns.send(ctxt.output, “EOM”, {data = data})
::done::
-- Get the offset of the pattern, we want to delete
local delete_pattern = “pattern to delete”
local delete_pattern_length = delete_pattern:len()
local pat_off, pat_end = data:find(old_pattern)
-- pattern is not present
if (not pat_off) then
goto send_data
end
-- If the data we want to delete is not completely present,
-- then wait for more data
if (not pat_end) then
ctxt:hold(data)
data = nil
goto done
end
data:delete(pat_off, delete_pattern_length)
::send_data::
ns.send(ctxt.output, “EOM”, {data = data})
::done::
-- Replace all the instances of the pattern with the new string
data:gsub(“old pattern”, “new string”)
-- Replace only 2 instances of “old pattern”
data:gsub(“old pattern”, “new string”, 2)
-- Insert new_string before all instances of “http”
data:gsub(“input data”, “(http)”, “new_string%1”)
-- Insert new_string after all instances of “http”
data:gsub(“input data”, “(http)”, “%1new_string”)
-- Insert new_string before only 2 instances of “http”
data:gsub(“input data”, “(http)”, “new_string%1”, 2)
クライアントまたはサーバーへのトラフィックの発信
-- If the input packet is not MQTT CONNECT type, then
-- send some error response to the client.
function client.on_data(ctxt, payload)
local data = payload.data
local offset = 1
local msg_type = 0
local error_response = “Missing MQTT Connect packet.”
byte = data:byte(offset)
msg_type = bit32.rshift(byte, 4)
if (msg_type ~= 1) then
-- Send the error response
ns.send(ctxt.client, “DATA”, {data = error_response})
-- Since error response has been sent, so now close the connection
ctxt:close()
end
-- After sending request, send some log message to the server.
function client.on_data(ctxt, payload)
local data = payload.data
local log_message = “client id : “..data:sub(3, 7)..” user name : “ data:sub(9, 15)
-- Send the request we get from the client to backend server
ns.send(ctxt.output, “DATA”, {data = data})
After sending the request, also send the log message
ns.send(ctxt.output, “DATA”, {data = log_message”})
end
-- If the HTTP response status message is “Not Found”,
-- then send another request to the server.
function server.on_data(ctxt, payload)
local data = 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
-- Send the another request to server
ns.send(ctxt.server, “DATA”, {data = request})
end
接続確立時のデータ処理
-- Send a request to the next processing context
-- on the connection establishment.
function client.init(ctxt)
local request “PROXY TCP4” + ctxt.client.ip.src.to_s + “ “ + ctxt.client.ip.dst.to_s + “ “ + ctxt.client.tcp.srcport + “ “ + ctxt.client.tcp.dstport
-- Send the another request to server
ns.send(ctxt.output, “DATA”, {data = request})
end