2017-02-08 6 views
0

マルチテナントREST APIシステムのレートリミッタとして動作するようにnginxを評価しています。テナントIDでAPI呼び出しを制限する必要があります。 たとえば、テナント1は100 r/s、テナント2は50 r/sしか許可しません。nginxをHTTP本体に基づくレートリミッタとして

"me.com/tenant1/api"と "me.com/tenant2/api"(ロケーションディレクティブ付き)のような異なるURLがある場合は、簡単に達成できます。

しかし、私の場合、すべてのテナント "me.com/api"のURLは同じです(私はこれを変更できません)。 テナントIDを見つけるには、リクエストのBodyからJSON属性を抽出し、実際のテナントIDをDBでチェックする必要があります。

私の要件でlimit_reqを使用することは可能ですか?

ありがとうございました!

+0

そのIDをHTTPヘッダーに入れることができるなら、あなたは 'limit_req_zone $ http_tenant_id ...'のようなことをすることができるはずです。それ以外の場合は、[map](http://nginx.org/en/docs/http/ngx_http_map_module.html#map)を使用して$ response_bodyからその値を抽出することができます。ありがとう@FaisalMemon。 –

+0

悲しいことに、私はhttpヘッダーを追加することはできません。 tenant-idを見つける唯一の方法は、Base64 JSON本体をデコードし、変数を抽出してDB(またはキャッシュ)で検索することです。 – Yarix

+0

ルアを使う必要があるような複雑な作業をするには:https://github.com/openresty/lua-nginx-module#readme –

答えて

0

身体を解析し、DBからテナントを抽出するために、別のサービスgetTenantを構築することに決めました。このサービスはNginxによって内部的に呼び出されます。 は、私はそれが最高のnginxの(/ openresty)ソリューションがあるかどうかわからないんだけど、これは私が思い付いたものです:me.com/apiが呼び出される基本的

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; 
    } 
} 

、新しいサブリクエスト/getTenantに発行されます。その呼び出しの応答は、/テナント[X]/doApiサービスへの別のサブ要求呼び出しを作成するために使用されます。そうすれば、私はテナントごとの場所を定義し、それぞれに異なるrate_limisを提供することができます。

歓迎以上のコメントです!

関連する問題