2014-10-16 126 views
3

我建設有瓶,寧靜的一兩件事,我想使REST API批處理API請求是能夠批量請求的資源,類似於Facebook的圖形API是如何工作的:用燒瓶寧靜

curl \ 
    -F 'access_token=…' \ 
    -F 'batch=[{"method":"GET", "relative_url":"me"},{"method":"GET", "relative_url":"me/friends?limit=50"}]' \ 
    https://graph.facebook.com 

,然後用它的狀態代碼,並因此解決每個請求返回一個數組:

[ 
    { "code": 200, 
     "headers":[ 
      { "name": "Content-Type", 
      "value": "text/javascript; charset=UTF-8" } 
     ], 
     "body": "{\"id\":\"…\"}"}, 
    { "code": 200, 
     "headers":[ 
      { "name":"Content-Type", 
      "value":"text/javascript; charset=UTF-8"} 
     ], 
     "body":"{\"data\": [{…}]}} 
] 

我已經能夠在燒瓶寧靜複製這種通過簡單地遍歷請求和呼籲的urlopen對我的自己的應用。這看起來效率很低,我不得不認爲有更好的方法。有沒有一種更簡單和/或更好的方法來在請求處理程序中針對我自己的應用程序提出請求?

回答

2

由於您需要返回標題,因此我建議您將這些批處理請求發送給自己(即將請求發送到localhost),這樣響應將與您在進行單獨調用時獲得的響應一致。

請注意,當您的API收到一個批處理請求時,您將需要至少一個空閒工作人員處理這些間接請求,同時第一個工作人員阻止並等待。所以你需要至少有兩名工人。即使如此,如果兩個批處理請求同時到達並帶走兩名工作人員,則可能會導致死鎖。因此,實際上,您需要擁有儘可能多的工人,因爲您希望同時收到批處理請求,並且至少還需要一個以處理間接請求。

從另一方面來看,您將希望並行運行儘可能多的這些間接請求,因爲如果它們最終一個接一個地運行,則使用批處理請求的好處會丟失。所以你也需要有足夠數量的工作人員來允許並行性。

誠實地說,我不認爲這是一個很棒的功能。在大多數客戶端語言中,並行執行多個請求相當容易,因此您不需要提供這是一個服務器端功能。特別容易,如果你正在使用Javascript,但也很容易在Python,紅寶石等。

+0

謝謝米格爾。我主要是爲API的移動應用程序消費者實現它,但是a)他們也可以非常簡單地執行並行請求,b)我認爲你是對的,這些好處並不值得。感謝有關死鎖的信息和一點點讓我意識到它根本不值得。 – 2014-10-17 10:15:14

1

您可以使用Flask來執行批處理中提交的各個請求,如下所示。

批請求

[ 
    { 
     "method" : <string:method>, 
     "path" : <string:path>, 
     "body" : <string:body> 
    }, 
    { 
     "method" : <string:method>, 
     "path" : <string:path>, 
     "body" : <string:body> 
    } 
] 

批量應答

[ 
    { 
     "status" : <int:status_code>, 
     "response" : <string:response> 
    }, 
    { 
     "status" : <int:status_code>, 
     "response" : <string:response> 
    } 
] 

示例代碼

def _read_response(response): 
    output = StringIO.StringIO() 
    try: 
     for line in response.response: 
      output.write(line) 

     return output.getvalue() 

    finally: 
     output.close() 

@app.route('/batch', methods=['POST']) 
def batch(username): 
    """ 
    Execute multiple requests, submitted as a batch. 

    :statuscode 207: Multi status 
    """ 
    try: 
     requests = json.loads(request.data) 
    except ValueError as e: 
     abort(400) 

    responses = [] 

    for index, req in enumerate(requests): 
     method = req['method'] 
     path = req['path'] 
     body = req.get('body', None) 

     with app.app_context(): 
      with app.test_request_context(path, method=method, data=body): 
       try: 
        # Can modify flask.g here without affecting flask.g of the root request for the batch 

        # Pre process Request 
        rv = app.preprocess_request() 

        if rv is None: 
         # Main Dispatch 
         rv = app.dispatch_request() 

       except Exception as e: 
        rv = app.handle_user_exception(e) 

       response = app.make_response(rv) 

       # Post process Request 
       response = app.process_response(response) 

     # Response is a Flask response object. 
     # _read_response(response) reads response.response and returns a string. If your endpoints return JSON object, 
     # this string would be the response as a JSON string. 
     responses.append({ 
      "status": response.status_code, 
      "response": _read_response(response) 
     }) 

    return make_response(json.dumps(responses), 207, HEADERS)