You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by me...@apache.org on 2020/02/24 02:58:23 UTC
[incubator-apisix] branch master updated: feat: plugin
`grpc-transcode` supports grpc deadline (#1149)
This is an automated email from the ASF dual-hosted git repository.
membphis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-apisix.git
The following commit(s) were added to refs/heads/master by this push:
new b66ff90 feat: plugin `grpc-transcode` supports grpc deadline (#1149)
b66ff90 is described below
commit b66ff90f1f7dc6630d1d9db78531417251c248b9
Author: nic-chen <33...@users.noreply.github.com>
AuthorDate: Mon Feb 24 10:58:15 2020 +0800
feat: plugin `grpc-transcode` supports grpc deadline (#1149)
---
lua/apisix/plugins/grpc-transcode.lua | 40 +++++++++-
lua/apisix/plugins/grpc-transcode/request.lua | 9 ++-
lua/apisix/plugins/grpc-transcode/response.lua | 44 +++++------
t/plugin/grpc-transcode.t | 105 +++++++++++++++++++++++++
4 files changed, 172 insertions(+), 26 deletions(-)
diff --git a/lua/apisix/plugins/grpc-transcode.lua b/lua/apisix/plugins/grpc-transcode.lua
index d16bfd6..21c8f42 100644
--- a/lua/apisix/plugins/grpc-transcode.lua
+++ b/lua/apisix/plugins/grpc-transcode.lua
@@ -53,8 +53,19 @@ local schema = {
type = "object",
properties = {
proto_id = schema_def.id_schema,
- service = { type = "string" },
- method = { type = "string" },
+ service = {
+ description = "the grpc service name",
+ type = "string"
+ },
+ method = {
+ description = "the method name in the grpc service.",
+ type = "string"
+ },
+ deadline = {
+ description = "deadline for grpc, millisecond",
+ type = "number",
+ default = 0
+ },
pb_option = { type = "array",
items = { type="string", anyOf = pb_option_def },
minItems = 1,
@@ -63,6 +74,17 @@ local schema = {
additionalProperties = true }
}
+local status_rel = {
+ ["3"] = 400,
+ ["4"] = 504,
+ ["5"] = 404,
+ ["7"] = 403,
+ ["11"] = 416,
+ ["12"] = 501,
+ ["13"] = 500,
+ ["14"] = 503,
+}
+
local _M = {
version = 0.1,
priority = 506,
@@ -102,7 +124,7 @@ function _M.access(conf, ctx)
end
local ok, err = request(proto_obj, conf.service,
- conf.method, conf.pb_option)
+ conf.method, conf.pb_option, conf.deadline)
if not ok then
core.log.error("transform request error: ", err)
return
@@ -119,6 +141,18 @@ function _M.header_filter(conf, ctx)
ngx.header["Content-Type"] = "application/json"
ngx.header["Trailer"] = {"grpc-status", "grpc-message"}
+
+ local headers = ngx.resp.get_headers()
+ if headers["grpc-status"] ~= nil and headers["grpc-status"] ~= "0" then
+ local http_status = status_rel[headers["grpc-status"]]
+ if http_status ~= nil then
+ ngx.status = http_status
+ else
+ ngx.status = 599
+ end
+ return
+ end
+
end
diff --git a/lua/apisix/plugins/grpc-transcode/request.lua b/lua/apisix/plugins/grpc-transcode/request.lua
index d985d66..1ce76c1 100644
--- a/lua/apisix/plugins/grpc-transcode/request.lua
+++ b/lua/apisix/plugins/grpc-transcode/request.lua
@@ -23,8 +23,9 @@ local ngx = ngx
local string = string
local table = table
local ipairs = ipairs
+local tonumber = tonumber
-return function (proto, service, method, pb_option, default_values)
+return function (proto, service, method, pb_option, deadline, default_values)
core.log.info("proto: ", core.json.delay_encode(proto, true))
local m = util.find_method(proto, service, method)
if not m then
@@ -62,5 +63,11 @@ return function (proto, service, method, pb_option, default_values)
ngx.req.set_uri("/" .. service .. "/" .. method, false)
ngx.req.set_uri_args({})
ngx.req.set_body_data(message)
+
+ local dl = tonumber(deadline)
+ if dl~= nil and dl > 0 then
+ ngx.req.set_header("grpc-timeout", dl .. "m")
+ end
+
return true
end
diff --git a/lua/apisix/plugins/grpc-transcode/response.lua b/lua/apisix/plugins/grpc-transcode/response.lua
index e764938..b2ce1dc 100644
--- a/lua/apisix/plugins/grpc-transcode/response.lua
+++ b/lua/apisix/plugins/grpc-transcode/response.lua
@@ -41,33 +41,33 @@ return function(proto, service, method, pb_option)
ngx.arg[1] = nil
end
- if not eof then
- return
- end
- ngx.ctx.buffered = nil
- local buffer = table.concat(buffered)
- if not ngx.req.get_headers()["X-Grpc-Web"] then
- buffer = string.sub(buffer, 6)
- end
+ if eof then
+ ngx.ctx.buffered = nil
+ local buffer = table.concat(buffered)
+ if not ngx.req.get_headers()["X-Grpc-Web"] then
+ buffer = string.sub(buffer, 6)
+ end
- if pb_option then
- for _, opt in ipairs(pb_option) do
- pb.option(opt)
+ if pb_option then
+ for _, opt in ipairs(pb_option) do
+ pb.option(opt)
+ end
end
- end
- local decoded = pb.decode(m.output_type, buffer)
- if not decoded then
- ngx.arg[1] = "failed to decode response data by protobuf"
- return
- end
+ local decoded = pb.decode(m.output_type, buffer)
+ if not decoded then
+ ngx.arg[1] = "failed to decode response data by protobuf"
+ return "failed to decode response data by protobuf"
+ end
+
+ local response, err = core.json.encode(decoded)
+ if not response then
+ core.log.error("failed to call json_encode data: ", err)
+ response = "failed to json_encode response body"
+ end
- local response, err = core.json.encode(decoded)
- if not response then
- core.log.error("failed to call json_encode data: ", err)
- response = "failed to json_encode response body"
+ ngx.arg[1] = response
end
- ngx.arg[1] = response
end
diff --git a/t/plugin/grpc-transcode.t b/t/plugin/grpc-transcode.t
index 81b9ec2..f778cc1 100644
--- a/t/plugin/grpc-transcode.t
+++ b/t/plugin/grpc-transcode.t
@@ -232,7 +232,9 @@ Connection refused) while connecting to upstream
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc Plus (PlusRequest) returns (PlusReply) {}
+ rpc SayHelloAfterDelay (HelloRequest) returns (HelloReply) {}
}
+
message HelloRequest {
string name = 1;
}
@@ -324,3 +326,106 @@ GET /grpc_plus?a=1&b=2251799813685260
qr/\{"result":"#2251799813685261"\}/
--- no_error_log
[error]
+
+
+
+=== TEST 11: set route3 deadline nodelay
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/3',
+ ngx.HTTP_PUT,
+ [[{
+ "methods": ["GET"],
+ "uri": "/grpc_deadline",
+ "service_protocol": "grpc",
+ "plugins": {
+ "grpc-transcode": {
+ "proto_id": "1",
+ "service": "helloworld.Greeter",
+ "method": "SayHello",
+ "deadline": 500
+ }
+ },
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "127.0.0.1:50051": 1
+ }
+ }
+ }]]
+ )
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 12: hit route
+--- request
+GET /grpc_deadline?name=apisix
+--- response_body eval
+qr/\{"message":"Hello apisix"\}/
+--- no_error_log
+[error]
+
+
+
+=== TEST 13: set route4 deadline delay
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/routes/4',
+ ngx.HTTP_PUT,
+ [[{
+ "methods": ["GET"],
+ "uri": "/grpc_delay",
+ "service_protocol": "grpc",
+ "plugins": {
+ "grpc-transcode": {
+ "proto_id": "1",
+ "service": "helloworld.Greeter",
+ "method": "SayHelloAfterDelay",
+ "deadline": 500
+ }
+ },
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "127.0.0.1:50051": 1
+ }
+ }
+ }]]
+ )
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 14: hit route
+--- request
+GET /grpc_delay?name=apisix
+--- error_code: 504
+
+