當前位置: 首頁>>技術問答>>正文


帶有要求的燒瓶破碎管

, , ,

問題描述

我想在一個燒瓶應用程序中發送一個本地REST請求,如下所示:

from flask import Flask, url_for, request
import requests

app = Flask(__name__)

@app.route("/<name>/hi", methods=["POST"])
def hi_person(name):
    form = {"name": name}
    return requests.post(url_for("hi", _external=True), data=form)

@app.route("/hi", methods=["POST"])
def hi():
    return 'Hi, %s!' % request.form["name"]

發送curl -X POST http://localhost:5000/john/hi會導致整個燒瓶應用程序凍結。當我發送一個kill信號時,我的管道出現故障。有沒有辦法防止燒瓶在這裏凍結?

最佳解決方案

在能夠處理並發請求(可能是gunicornuWSGI)的適當WSGI服務器下運行您的燒瓶應用程序,它將工作。在開發時,在Flask-supplied服務器中啟用線程:

app.run(threaded=True)

但請注意,不建議將Flask服務器用於生產用途。從Flask 1.0開始,默認情況下啟用threaded,並且您希望在命令行上使用flask命令來運行您的應用程序。

會發生的是使用請求您向燒瓶應用程序發出第二個請求,但由於它仍在忙於處理第一個請求,因此在完成第一個請求之前,它不會響應第二個請求。

順便說一句,在Python 3下,socketserver實現更優雅地處理斷開連接並繼續服務而不是崩潰。

次佳解決方案

這裏有幾件事情,我會嘗試解決它們one-at-a時間問題。

首先,您可能正在使用玩具開發服務器。這台服務器有很多局限性;主要是這些限製之一是它一次隻能處理一個請求。在第一次請求期間創建第二個請求時,您正在鎖定應用程序:requests.post()函數正在等待Flask響應,但Flask本身正在等待post()返回!此特定問題的解決方案是在多線程或多進程環境中運行WSGI應用程序。我更喜歡http://twistedmatrix.com/trac/wiki/TwistedWeb,但還有其他一些選擇。

順便說一下……這是一個反模式。您幾乎肯定不想僅僅為了在兩個視圖之間共享某些功能而調用HTTP請求的所有開銷。正確的做法是重構一個單獨的函數來完成共享工作。我無法重構你的特定例子,因為你所擁有的非常簡單,甚至不值得兩個觀點。你到底想要建造什麽?

編輯:注釋詢問玩具stdlib服務器中的多線程模式是否足以防止發生死鎖。我要說”maybe.”是的,如果沒有任何依賴關係讓兩個線程都沒有進展,並且兩個線程都有足夠的進度來完成他們的網絡任務,那麽請求將正確完成。但是,確定兩個線程是否會相互死鎖是不可判定的(證明省略為鈍)並且我不願意確定stdlib服務器可以正確執行。

第三種解決方案

導致崩潰的錯誤是fixed in Version 0.12,於2016年12月21日發布。是的!這是許多人一直在等待的重要修複。

來自Flask更改日誌:

  • Revert a behavior change that made the dev server crash instead of returning a Internal Server Error (pull request #2006).

參考資料

本文由Ubuntu問答整理, 博文地址: https://ubuntuqa.com/zh-tw/article/7222.html,未經允許,請勿轉載。