最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Django異步任務(wù)線程池實(shí)現(xiàn)原理

 更新時(shí)間:2019年12月17日 08:30:24   作者:luozx207  
這篇文章主要介紹了Django異步任務(wù)線程池實(shí)現(xiàn)原理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

這篇文章主要介紹了Django異步任務(wù)線程池實(shí)現(xiàn)原理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

當(dāng)數(shù)據(jù)庫數(shù)據(jù)量很大時(shí)(百萬級),許多批量數(shù)據(jù)修改請求的響應(yīng)會(huì)非常慢,一些不需要即時(shí)響應(yīng)的任務(wù)可以放到后臺(tái)的異步線程中完成,發(fā)起異步任務(wù)的請求就可以立即響應(yīng)

選擇用線程池的原因是:線程比進(jìn)程更為可控。不像子進(jìn)程,子線程會(huì)在所屬進(jìn)程結(jié)束時(shí)立即結(jié)束。線程可共享內(nèi)存。

請求任務(wù)異步處理的原理

使用python manage.py runserver模式啟動(dòng)的Django應(yīng)用只有一個(gè)進(jìn)程,對于每個(gè)請求,主線程會(huì)開啟一個(gè)子線程來處理請求。請求子線程向主線程申請一個(gè)新線程,然后把耗時(shí)的任務(wù)交給新線程,自身立即響應(yīng),這就是請求任務(wù)異步處理的原理。

可視化線程池

如果想要管理這批異步線程,知道他們是否在運(yùn)行中,可以使用線程池(ThreadPoolExecutor)。

線程池會(huì)先啟動(dòng)若干數(shù)量的線程,并讓這些線程都處于睡眠狀態(tài),當(dāng)向線程池submit一個(gè)任務(wù)后,會(huì)喚醒線程池中的某一個(gè)睡眠線程,讓它來處理這個(gè)任務(wù),當(dāng)處理完這個(gè)任務(wù),線程又處于睡眠狀態(tài)。

submit任務(wù)后會(huì)返回一個(gè)期程(future),這個(gè)對象可以查看線程池中執(zhí)行此任務(wù)的線程是否仍在處理中

因此可以構(gòu)建一個(gè)全局可視化線程池:

from concurrent.futures.thread import ThreadPoolExecutor


class ThreadPool(object):
  def __init__(self):
    # 線程池
    self.executor = ThreadPoolExecutor(20)
    # 用于存儲(chǔ)每個(gè)項(xiàng)目批量任務(wù)的期程
    self.future_dict = {}

  # 檢查某個(gè)項(xiàng)目是否有正在運(yùn)行的批量任務(wù)
  def is_project_thread_running(self, project_id):
    future = self.future_dict.get(project_id, None)
    if future and future.running():
      # 存在正在運(yùn)行的批量任務(wù)
      return True
    return False

  # 展示所有的異步任務(wù)
  def check_future(self):
    data = {}
    for project_id, future in self.future_dict.items():
      data[project_id] = future.running()
    return data

  def __del__(self):
    self.executor.shutdown()

# 主線程中的全局線程池
# global_thread_pool的生命周期是Django主線程運(yùn)行的生命周期
global_thread_pool = ThreadPool()

使用:

# 檢查異步任務(wù)
if global_thread_pool.is_project_thread_running(project_id):
  raise exceptions.ValidationError(detail='存在正在處理的批量任務(wù),請稍后重試')

# 提交一個(gè)異步任務(wù)
future = global_thread_pool.executor.submit(self.batch_thread, project_id)
global_thread_pool.future_dict[project_id] = future

# 查看所有異步任務(wù)
@login_required
def check_future(request):
  data = global_thread_pool.check_future()
  return HttpResponse(status=status.HTTP_200_OK, content=json.dumps(data))

串行執(zhí)行

使用線程鎖

在全局線程池中初始化線程鎖

class ThreadPool(object):
  def __init__(self):
    self.executor = ThreadPoolExecutor(20)
    self.future_dict = {}
    self.lock = threading.Lock()

然后執(zhí)行線程前需要獲取鎖并再執(zhí)行結(jié)束后釋放鎖

def batch_thread(self):
  global_thread_pool.lock.acquire()
  try:
    ...
    global_thread_pool.lock.release()
  except Exception:
    trace_log = traceback.format_exc()
    logger.error('異步任務(wù)執(zhí)行失敗:\n %s' % trace_log)
    global_thread_pool.lock.release()

需要捕捉異常預(yù)防子線程出錯(cuò)而無法釋放鎖的情況

異步線程任務(wù)執(zhí)行前先檢查數(shù)據(jù)庫連接是否可用,然后關(guān)掉不可用連接

由于django的數(shù)據(jù)庫連接是保存到線程本地變量中的,通過ThreadPoolExecutor創(chuàng)建的線程會(huì)保存各自的數(shù)據(jù)庫連接。

當(dāng)連接被保存的時(shí)間超過mysql連接的最大超時(shí)時(shí)間,連接失效,但不會(huì)被線程釋放。

之后再調(diào)起線程執(zhí)行涉及到數(shù)據(jù)庫操作的異步任務(wù)時(shí),會(huì)用到失效的數(shù)據(jù)庫連接,導(dǎo)致報(bào)錯(cuò)“MySQL server has gone away”。

解決方案是在線程池的所有異步任務(wù)執(zhí)行前先檢查數(shù)據(jù)庫連接是否可用,然后關(guān)掉不可用連接

def batch_thread(self):
  for conn in connections.all():
    conn.close_if_unusable_or_obsolete()
  ...

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • pycharm配置當(dāng)鼠標(biāo)懸停時(shí)快速提示方法參數(shù)

    pycharm配置當(dāng)鼠標(biāo)懸停時(shí)快速提示方法參數(shù)

    這篇文章主要介紹了pycharm中配置當(dāng)鼠標(biāo)懸停時(shí)快速提示方法參數(shù),本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-07-07
  • Python使用微信itchat接口實(shí)現(xiàn)查看自己微信的信息功能詳解

    Python使用微信itchat接口實(shí)現(xiàn)查看自己微信的信息功能詳解

    這篇文章主要介紹了Python使用微信itchat接口實(shí)現(xiàn)查看自己微信的信息功能,結(jié)合實(shí)例形式分析了Python微信itchat模塊常見功能與操作技巧,需要的朋友可以參考下
    2019-08-08
  • Python2和Python3.6環(huán)境解決共存問題

    Python2和Python3.6環(huán)境解決共存問題

    這篇文章主要介紹了Python2和Python3.6環(huán)境解決共存問題,需要的朋友可以參考下
    2018-11-11
  • 一文帶你深度解密Python的字節(jié)碼

    一文帶你深度解密Python的字節(jié)碼

    當(dāng)我們想要執(zhí)行一個(gè)?py?文件的時(shí)候,只需要在命令行中輸入?python?xxx.py?即可,但你有沒有想過這背后的流程是怎樣的呢?本文主要賀和大家來聊聊Python中的字節(jié)碼,感興趣的可以了解一下
    2022-12-12
  • Python項(xiàng)目管理的利器Poetry的使用

    Python項(xiàng)目管理的利器Poetry的使用

    在?Python?項(xiàng)目開發(fā)中,包管理、依賴管理和虛擬環(huán)境的創(chuàng)建一直是開發(fā)者們經(jīng)常面對的難題,本文主要介紹了Python項(xiàng)目管理的利器Poetry的使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-04-04
  • Python?中?yeild?的用法詳解

    Python?中?yeild?的用法詳解

    yield?是?Python?中的關(guān)鍵字,用于生成器函數(shù)中,可以將函數(shù)變成一個(gè)迭代器,實(shí)現(xiàn)惰性計(jì)算,節(jié)省內(nèi)存空間。本文將介紹?yield?的基本用法和實(shí)現(xiàn)原理,以及與?yield?相關(guān)的注意事項(xiàng)和常見問題。
    2023-06-06
  • Python?matplotlib實(shí)現(xiàn)多子圖布局

    Python?matplotlib實(shí)現(xiàn)多子圖布局

    多子圖布局是指在一個(gè)圖像中同時(shí)顯示多個(gè)子圖,每個(gè)子圖可以是獨(dú)立的圖形或者是相互關(guān)聯(lián)的圖形,下面我們就來了解下matplotlib是如何實(shí)現(xiàn)多子圖布局的吧
    2023-12-12
  • 如何用python做簡單的接口壓力測試

    如何用python做簡單的接口壓力測試

    這篇文章主要介紹了如何用python做簡單的接口壓力測試問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Python快速轉(zhuǎn)換numpy數(shù)組中Nan和Inf的方法實(shí)例說明

    Python快速轉(zhuǎn)換numpy數(shù)組中Nan和Inf的方法實(shí)例說明

    今天小編就為大家分享一篇關(guān)于Python快速轉(zhuǎn)換numpy數(shù)組中Nan和Inf的方法實(shí)例說明,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • Python實(shí)現(xiàn)手繪圖效果實(shí)例分享

    Python實(shí)現(xiàn)手繪圖效果實(shí)例分享

    在本篇文章里小編給大家整理了關(guān)于Python實(shí)現(xiàn)手繪圖效果,有需要的朋友們可以學(xué)習(xí)下。
    2020-07-07

最新評論

雷波县| 恩平市| 白山市| 嘉兴市| 叙永县| 永春县| 科技| 天等县| 兴化市| 汉阴县| 洛扎县| 昌黎县| 平阳县| 民勤县| 大同县| 安图县| 通江县| 宁河县| 贵溪市| 沅江市| 丹巴县| 聂荣县| 城固县| 彰化市| 日土县| 长寿区| 巴楚县| 呈贡县| 改则县| 会同县| 蓬莱市| 临沭县| 集安市| 托克托县| 永和县| 侯马市| 兴海县| 南华县| 宕昌县| 忻城县| 克山县|