簡體   English   中英

如何處理 Django 中的同時請求?

[英]How to handle simultaneous requests in Django?

我在 Django 中有一個標准的基於函數的視圖,它在用戶單擊按鈕后通過 POST 接收一些參數,計算一些東西然后返回一個帶有上下文的模板。

@csrf_exempt
def myview(request, param1, param2):

   if request.method == 'POST':
      return HttpResponseRedirect(reverse("app1:view_name", args=[param1, param2]))

   '''Calculate and database r/w'''

   template = loader.get_template('showData.html')
   return HttpResponse(template.render(context, request))

只要當時處理一個請求,它就沒有問題(使用 runserver 和 Apache 服務器進行了測試)。

但是,當我使用兩個設備並同時單擊每個設備中的按鈕時,兩個請求混合在一起,同時運行,網站最終出現 500 錯誤,或 404 或有時成功但無法獲取 static 文件..(再次,使用 runserver 和 Apache 進行了測試)。

如何強制 Django 在開始下一個請求之前完成當前請求的執行? 或者有更好的方法來解決這個問題嗎?

對此的任何了解將不勝感激。 謝謝!

協調單個服務器進程內的線程,請使用

from threading import RLock

lock = RLock()

然后在myview

    lock.acquire()
    ...  # get template, render it
    lock.release()

您可以使用$ uwsgi --processes 1 --threads 2...啟動您的服務器

Django web 本地機器上的服務器不適用於生產環境。 因此它一次處理一個請求。 在生產中,你需要使用 WSGI 服務器,比如 uwsgi。 這樣一來,您的應用程序就可以設置為一次處理多個請求。 檢查https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/uwsgi/

我發布我的解決方案以防對其他人有任何幫助。

最后,我為 Apache 配置了一個預分叉來隔離彼此的請求。 根據文檔,建議對使用非線程安全庫的站點進行預分叉(顯然是我的情況)。

通過此修復,Apache 可以很好地處理並發請求。 但是,如果有人有其他建議,我仍然會很高興聽到!

應該有辦法重寫代碼,這樣事情就不會混淆了。 (至少在很多情況下這是可能的)

前提條件之一(如果您的服務器使用Lock )是編寫線程安全代碼線程安全。 (或用Lock保護它們)

由於您未提供任何詳細信息,因此我們無法提供幫助。 (這 = 找到一種阻塞整個請求但保持數據完整性的方法)

否則,您可以使用跨多個進程的互斥鎖/鎖。

例如,您可以嘗試訪問一個鎖定的文件https://pypi.org/project/filelock/並阻止,直到該文件被另一個視圖解鎖。

示例代碼(在 pip 安裝文件鎖之后)

from filelock import FileLock
lock = FileLock("my.lock")
with lock:
    if request.method == 'POST':
        return HttpResponseRedirect(reverse("app1:view_name", args=[param1, param2]))

    '''Calculate and database r/w'''

    template = loader.get_template('showData.html')
    return HttpResponse(template.render(context, request))

如果你使用 uwsgi,那么你可以查看鎖的 uwsgi 實現:

https://uwsgi-docs.readthedocs.io/en/latest/Locks.html

這里是 uwsgi 文檔中的示例代碼:

def use_lock_zero_for_important_things():
    uwsgi.lock() # Implicit parameter 0
    # Critical section
    uwsgi.unlock() # Implicit parameter 0

def use_another_lock():
    uwsgi.lock(1)
    time.sleep(1) # Take that, performance! Ha!
    uwsgi.unlock(1)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM