我決定建立另一個服務getTenant解析正文並從數據庫中提取租戶。此服務由Nginx內部調用。 我不知道這是最好的nginx(/ openresty)解決方案,但是這是我想出了:
limit_req_zone t1Limit zone=t1Zone:10m rate=200r/s;
limit_req_zone t2Limit zone=t2Zone:10m rate=90r/s;
server {
location /api{
content_by_lua_block {
ngx.req.read_body();
local reqBody = ngx.req.get_body_data()
local res = ngx.location.capture("/getTenant", {method=ngx.HTTP_POST,body=reqBody});
local tenantId= res.body;
if tenantId== "none" then
ngx.log(ngx.ERR, "Tenant not found!");
ngx.say(tenantId);
else
ngx.req.set_header("x_myTenantId", tenantId)
local res2 = ngx.location.capture("/" .. tenantId .."/doApi", {method=ngx.HTTP_POST,body=reqBody});
if res2.status == ngx.HTTP_OK then
ngx.say(res2.body);
ngx.exit(res2.status);
else
ngx.status = res2.status
ngx.exit(res2.status)
end
end;
}
}
location /getTenant {
internal; #this is not accessible from outside.
proxy_pass http://UpStream1/getCustomer;
proxy_set_header X-Original-URI $request_uri;
}
location /tenant1/doApi {
internal; #this is not accessible from outside.
# Proxy all requests to the AReqUpStream server group
proxy_pass http://UpStream2/doApi;
limit_req zone=tenant1Zone burst=25;
limit_req_log_level notice;
}
location /tenant2/doApi {
internal; #this is not accessible from outside.
# Proxy all requests to the AReqUpStream server group
proxy_pass http://UpStream2/doApi;
limit_req zone=tenant2Zone burst=10 ;#nodelay;
limit_req_status 409;
limit_req_log_level notice;
}
}
基本上,當me.com/api被調用時,一個新的子請求頒發給服務/getTenant。該呼叫的響應用於建立另一個子請求調用/tenant [X]/doApi服務。這樣我可以定義每個租戶的位置併爲每個租戶提供不同的rate_limis。
上的評論非常歡迎!
如果你可以把這個ID作爲一個HTTP頭,那麼你應該能夠做到像'limit_req_zone $ http_tenant_id ...'。否則,您可能可以使用[map](http://nginx.org/en/docs/http/ngx_http_map_module.html#map)從$ response_body中提取該值。 –
謝謝@FaisalMemon。可悲的是,我無法添加http頭。找到tenant-id的唯一方法是解碼Base64 JSON體,提取一些變量並在數據庫(或緩存)中搜索它。 – Yarix
做複雜的東西一樣,你可能不得不使用Lua的:https://github.com/openresty/lua-nginx-module#readme –