1. 程式人生 > >協程、同步非同步、併發、並行、rabbitmq、分散式任務佇列

協程、同步非同步、併發、並行、rabbitmq、分散式任務佇列

http://docs.jinkan.org/docs/celery/

協程

協程不是程序或執行緒,其執行過程更類似於不帶返回值的函式呼叫。

一個程式可以包含多個協程,可以對比與一個程序包含多個執行緒。我們知道多個執行緒相對獨立,有自己的上下文,切換受系統控制;而協程也相對獨立,有自己的上下文,但是其切換由自己控制,由當前協程切換到其他協程由當前協程來控制。

https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868328689835ecd883d910145dfa8227b539725e5ed000

子程式,或者稱為函式,在所有語言中都是層級呼叫,比如A呼叫B,B在執行過程中又呼叫了C,C執行完畢返回,B執行完畢返回,最後是A執行完畢。所以子程式呼叫是通過棧實現的,一個執行緒就是執行一個子程式。

子程式呼叫總是一個入口,一次返回,呼叫順序是明確的。而協程的呼叫和子程式不同。

協程看上去也是子程式,但執行過程中,在子程式內部可中斷,然後轉而執行別的子程式,在適當的時候再返回來接著執行。

協程的特點在於是一個執行緒執行,那和多執行緒比,協程有何優勢?

最大的優勢就是協程極高的執行效率。因為子程式切換不是執行緒切換執行緒切換:當CPU從執行一個執行緒切換到執行另外一個執行緒的時候,它需要先儲存當前執行緒的本地的資料,程式指標等,然後載入另一個執行緒的本地資料,程式指標等,最後才開始執行執行緒在執行的時候需要從計算機裡面得到一些資源。除了CPU,執行緒還需要一些記憶體來維持它本地的堆疊。它也需要佔用作業系統中一些資源來管理執行緒

增加了資源消耗,而是由程式自身控制,因此,沒有執行緒切換的開銷,和多執行緒比,執行緒數量越多,協程的效能優勢就越明顯。

第二大優勢就是不需要多執行緒的鎖機制,因為只有一個執行緒,也不存在同時寫變數衝突,在協程中控制共享資源不加鎖,只需要判斷狀態就好了,所以執行效率比多執行緒高很多。

因為協程是一個執行緒執行,那怎麼利用多核CPU呢?最簡單的方法是多程序+協程,既充分利用多核,又充分發揮協程的高效率,可獲得極高的效能。

Python對協程的支援還非常有限,用在generator中的yield可以一定程度上實現協程。雖然支援不完全,但已經可以發揮相當大的威力了

線性表

棧(stack)又名堆疊,它是一種運算受限的線性表。其限制是僅允許在表的一端進行插入和刪除運算。這一端被稱為棧頂,相對地,把另一端稱為棧底。向一個棧插入新元素又稱作進棧、入棧或壓棧,它是把新元素放到棧頂元素的上面,使之成為新的棧頂元素;從一個棧刪除元素又稱作出棧或退棧,它是把棧頂元素刪除掉,使其相鄰的元素成為新的棧頂元素。

特點:先進後出

佇列是一種特殊的線性表,特殊之處在於它只允許在表的前端(front)進行刪除操作,而在表的後端(rear)進行插入操作,和棧一樣,佇列是一種操作受限制的線性表。進行插入操作的端稱為隊尾,進行刪除操作的端稱為隊頭。

特點:先進先出

同步非同步

同步和非同步的概念對於很多人來說是一個模糊的概念,是一種似乎只能意會不能言傳的東西。其實我們的生活中存在著很多同步非同步的例子。比如:你叫我去吃飯,我聽到了就立刻和你去吃飯,如果我們有聽到,你就會一直叫我,直到我聽見和你一起去吃飯,這個過程叫同步;非同步過程指你叫我去吃飯,然後你就去吃飯了,而不管我是否和你一起去吃飯。而我得到訊息後可能立即就走,也可能過段時間再走

在計算機領域,同步就是指一個程序在執行某個請求的時候,若該請求需要一段時間才能返回資訊,那麼這個程序將會一直等待下去,直到收到返回資訊才繼續執行下去;非同步是指程序不需要一直等下去,而是繼續執行下面的操作,不管其他程序的狀態。當有訊息返回時系統會通知程序進行處理,這樣可以提高執行的效率。

而我們平時經常討論的同步問題多發生在多執行緒環境中的資料共享問題。即當多個執行緒需要訪問同一個資源時,它們需要以某種順序來確保該資源在某一特定時刻只能被一個執行緒所訪問,如果使用非同步,程式的執行結果將不可預料。因此,在這種情況下,就必須對資料進行同步,即限制只能有一個程序訪問資源,其他執行緒必須等待。

實現同步的機制主要有臨界區、互斥、訊號量和事件

臨界區:通過對多執行緒的序列化來訪問公共資源或一段程式碼,速度快,適合控制資料訪問。在任意時刻只允許一個執行緒對共享資源進行訪問,如果有多個執行緒試圖訪問公共資 源,那麼在有一個執行緒進入後,其他試圖訪問公共資源的執行緒將被掛起,並一直等到進入臨界區的執行緒離開,臨界區在被釋放後,其他執行緒才可以搶佔。

互斥量:採用互斥物件機制。 只有擁有互斥物件的執行緒才有訪問公共資源的許可權,因為互斥物件只有一個,所以能保證公共資源不會同時被多個執行緒訪問。互斥不僅能實現同一應用程式的公共資源安全共享,還能實現不同應用程式的公共資源安全共享 .互斥量比臨界區複雜。因為使用互斥不僅僅能夠在同一應用程式不同執行緒中實現資源的安全共享,而且可以在不同應用程式的執行緒之間實現對資源的安全共享。

訊號量:它允許多個執行緒在同一時刻訪問同一資源,但是需要限制在同一時刻訪問此資源的最大執行緒數目 。訊號量物件對執行緒的同步方式與前面幾種方法不同,訊號允許多個執行緒同時使用共享資源,這與作業系統中的PV操作相同。它指出了同時訪問共享資源的執行緒最大數目。它允許多個執行緒在同一時刻訪問同一資源,但是需要限制在同一時刻訪問此資源的最大執行緒數目。

事件:通過通知操作的方式來保持執行緒的同步,還可以方便實現對多個執行緒的優先順序比較的操作 。

併發

併發當有多個執行緒在操作時,如果系統只有一個CPU,則它根本不可能真正同時進行一個以上的執行緒,它只能把CPU執行時間劃分成若干個時間段,再將時間 段分配給各個執行緒執行,在一個時間段的執行緒程式碼執行時,其它執行緒處於掛起狀。.這種方式我們稱之為併發(Concurrent)。

並行:當系統有一個以上CPU時,則執行緒的操作有可能非併發。當一個CPU執行一個執行緒時,另一個CPU可以執行另一個執行緒,兩個執行緒互不搶佔CPU資源,可以同時進行,這種方式我們稱之為並行(Parallel)。

區別:併發和並行是即相似又有區別的兩個概念,並行是指兩個或者多個事件在同一時刻發生;而併發是指兩個或多個事件在同一時間間隔內發生。在多道程式環境下,併發性是指在一段時間內巨集觀上有多個程式在同時執行,但在單處理機系統中,每一時刻卻僅能有一道程式執行,故微觀上這些程式只能是分時地交替執行。倘若在計算機系統中有多個處理機,則這些可以併發執行的程式便可被分配到多個處理機上,實現並行執行,即利用每個處理機來處理一個可併發執行的程式,這樣,多個程式便可以同時執行。

rabbitmq

MQ全稱為Message Queue, 訊息佇列(MQ)是一種應用程式對應用程式的通訊方法。應用程式通過讀寫出入佇列的訊息(針對應用程式的資料)來通訊,而無需專用連線來連結它們。訊息傳遞指的是程式之間通過在訊息中傳送資料進行通訊,而不是通過直接呼叫彼此來通訊,直接呼叫通常是用於諸如遠端過程呼叫的技術。排隊指的是應用程式通過 佇列來通訊。佇列的使用除去了接收和傳送應用程式同時執行的要求。其中較為成熟的MQ產品有IBM WEBSPHERE MQ等等。

MQ特點

MQ是消費-生產者模型的一個典型的代表,一端往訊息佇列中不斷寫入訊息,而另一端則可以讀取或者訂閱佇列中的訊息。

使用場景

在專案中,將一些無需即時返回且耗時的操作提取出來,進行了非同步處理,而這種非同步處理的方式大大的節省了伺服器的請求響應時間,從而提高了系統的吞吐量。

使用

1.以預設的賬號密碼,賬號密碼都為guest,進入rabbitmq,127.0.0.1:15672

2.新建賬號:

Guest賬戶只能本機訪問,遠端訪問的話,只能新建賬號密碼。

選擇Admin,

輸入要新建的賬戶,密碼及確認密碼。

將此賬戶設為管理員賬號。

2.設定目錄:

通常我們會將佇列放入其他目錄下,安全考慮。

選擇

然後在,輸入要新建的目錄,新增即可。

3.為新增的目錄設定賬戶:

點選spider賬戶,進入

從,選擇 /spider即可。

最後的結果為:

Celery

分散式任務佇列

Celery 是一個簡單、靈活且可靠的,處理大量訊息的分散式系統,並且提供維護這樣一個系統的必需工具。

它是一個專注於實時處理的任務佇列,同時也支援任務排程。

任務佇列

任務佇列是一種線上程或機器間分發任務的機制。

訊息佇列

訊息佇列的輸入是工作的一個單元,稱為任務,獨立的職程(Worker)程序持續監視佇列中是否有需要處理的新任務。

Celery 用訊息通訊,通常使用中間人(Broker)在客戶端和職程間斡旋。這個過程從客戶端向佇列新增訊息開始,之後中間人把訊息派送給職程,職程對訊息進行處理。如下圖所示:

Celery 系統可包含多個職程和中間人,以此獲得高可用性和橫向擴充套件能力。

Celery的架構

Celery的架構由三部分組成,訊息中介軟體(message broker),任務執行單元(worker)和任務執行結果儲存(task result store)組成。

訊息中介軟體

Celery本身不提供訊息服務,但是可以方便的和第三方提供的訊息中介軟體整合,包括,RabbitMQ,Redis,MongoDB等。

任務執行單元

Worker是Celery提供的任務執行的單元,worker併發的執行在分散式的系統節點中

任務結果儲存

Task result store用來儲存Worker執行的任務的結果,Celery支援以不同方式儲存任務的結果,包括Redis,MongoDB,mysql等。

安裝:

pip install celery

pip install eventlet

#ss.py

# coding=utf-8

# 匯入celery包from celery import Celery# 匯入Exchange, Queue,連線rabbitmq的交換機和佇列from kombu import Exchange, Queue# 需求請求時匯入requests包import requestsrequests.packages.urllib3.disable_warnings()# 啟動命令# 即worker,cmd命令後,轉入到此檔案所在目錄,然後執行此命令。

# celery -A  ss worker -P eventlet -c 3 --loglevel=info# 其中  ss為檔名,3為協程數,這兩處可以自己定義# 初始化celeryapp = Celery()# 宣告連線到rabbitmq中的佇列為ssQueueName = "ss"# 引數設定celeryapp.conf.update(# 中間人設定BROKER_URL="amqp://spider:[email protected]:5672//spider",# 配置序列化任務載荷的預設的序列化方式CELERY_TASK_SERIALIZER='json',# 忽略接收其他內容CELERY_ACCEPT_CONTENT=['json'],# 結果序列號CELERY_RESULT_SERIALIZER='json',# 設定時區CELERY_TIMEZONE='Asia/Shanghai',# 使用UTC的方式,UTC的時間、時區、時差CELERY_ENABLE_UTC=True,# 配置佇列CELERY_QUEUES=(        Queue(QueueName, Exchange(QueueName), routing_key=QueueName),    ),# 預設佇列CELERY_DEFAULT_QUEUE=QueueName,# 連線方式CELERY_DEFAULT_EXCHANGE_TYPE='direct',# 路由佇列CELERY_DEFAULT_ROUTING_KEY=QueueName,# 任務執行結果的超時時間CELERY_TASK_RESULT_EXPIRES=1800,# worker 每次取任務的數量CELERYD_PREFETCH_MULTIPLIER=1,# 每個worker最多執行完10個任務就會被銷燬,可防止記憶體洩露CELERYD_MAX_TASKS_PER_CHILD=10,#  非常重要,有些情況下可以防止死鎖CELERYD_FORCE_EXECV=True,# 可以讓Celery更加可靠,只有當worker執行完任務後,才會告訴MQ,訊息被消費CELERY_ACKS_LATE=True,# 單個任務的執行時間不超過此值,否則會被SIGKILL 訊號殺死CELERYD_TASK_TIME_LIMIT=600,#  任務發出後,經過一段時間還未收到acknowledge , 就將任務重新交給其他worker執行  CELERY_DISABLE_RATE_LIMITS=True)@app.taskdef add(x, y):return x + y

#sa.py

# coding=utf-8import sstry:for in xrange(1,10):        ss.add.delay(i, i)#delay實現非同步,關鍵的部分except Exception,ex:print ex.messageprint 'end'

相關推薦

python# 程序/執行緒/ # IO:同步/非同步/阻塞/非阻塞 # greenlet gevent # 事件驅動與非同步IO # Select\Poll\Epoll非同步IO 以及selector

# 程序/執行緒/協程 # IO:同步/非同步/阻塞/非阻塞 # greenlet gevent # 事件驅動與非同步IO # Select\Poll\Epoll非同步IO 以及selectors模組 # Python佇列/RabbitMQ佇列   ###########

同步非同步併發並行rabbitmq分散式任務佇列

http://docs.jinkan.org/docs/celery/ 協程 協程不是程序或執行緒,其執行過程更類似於不帶返回值的函式呼叫。 一個程式可以包含多個協程,可以對比與一個程序包含多個執行緒。我們知道多個執行緒相對獨立,有自己的上下文,切換受系統控制;而協程也相對獨立,有自己的上下文,但是

併發程式設計】對阻塞/非阻塞同步/非同步併發/並行等基本概念的理解

1. 併發與並行 併發:concurrency 並行:parallelism 開發過程中,常常會接觸併發有關的概念,比如併發計算(concurrent computing),併發系統( concurrent system),併發控制(concurrent

Windows I/O模型同步/非同步阻塞/非阻塞

同步  所謂同步,就是在發出一個功能呼叫時,在沒有得到結果之前,該呼叫就不返回。按照這個定義,其實絕大多數函式都是同步呼叫(例如sin, isdigit等)。但是一般而言,我們在說同步、非同步的時候,特指那些需要其他部件協作或者需要一定時間完成的任務。最常見的例子就是 SendMessag

python GIL鎖程序池與執行緒池同步非同步

一、GIL全域性直譯器鎖 全域性直譯器鎖 在CPython中,全域性直譯器鎖(GIL)是一個互斥鎖,它可以防止多個本機執行緒同時執行Python程式碼。之所以需要這個鎖,主要是因為CPython的記憶體管理不是執行緒安全的。(然而,自從GIL存在以來,其他特性已經逐漸依賴於它所執行的保證)

Java多執行緒同步非同步及阻塞和非阻塞

1、程序和執行緒的概念 程序:執行中的應用程式稱為程序,擁有系統資源(cpu、記憶體) 執行緒:程序中的一段程式碼,一個程序中可以有多段程式碼。本身不擁有資源(共享所在程序的資源); 在java中,程式入口被自動建立為主執行緒,在主執行緒中可以建立多個子執

你真的瞭解:IIS連線數IIS併發連線數IIS最大併發工作執行緒數應用程式池的佇列長度應用程式池的...

IIS連線數 一般購買過虛擬主機的朋友都熟悉購買時,會限制IIS連線數,這邊先從普通不懂程式碼使用者角度理解IIS連線數 顧名思義即為IIS伺服器可以同時容納客戶請求的最高連線數,準確的說應該叫“IIS限制連線數” 這邊客戶請求的連線內容包括: 1、網站html請

同步非同步併發並行

     同步可以看成一個單執行緒操作,只要客戶端請求了,在伺服器沒有反饋資訊之前是一個執行緒阻塞狀態。(同步是多個執行緒同時訪問統一資源,等待資源訪問結束,浪費時間,效率低。)     非同步:看成多執行緒,在客戶端請求時,可以執行其

python--asyncio模組(基礎併發測試)

在高併發的場景下,python提供了一個多執行緒的模組threading,但似乎這個模組並不近人如意,原因在於cpython本身的全域性解析鎖(GIL)問題,在一段時間片內實際上的執行是單執行緒的。同時還存在著資源爭奪的問題。python3.4之後引入了基於生成器物件的協程概念。也就是asyncio模組。除了

python同步

協程與非同步   協程簡介:   協程又稱之為微執行緒,協程看上去也是子程式,但在執行的過程中,在子程式內部可中斷,然後轉而執行別的子程式,在適當的時候返回來接著執行程式。當然子程式是協程的特列。  個人見解:協程相當與在子程式(假設稱之為A程式)執行的過程中執行到一定的步驟後可以進

淺談Lua的Coroutine-的多"執行緒"併發模型

看了一下《Programming in Lua》裡的協程程式的運用,總覺得有點像霧裡看花一樣,捉不到重點,不知道怎麼去運用,但在洗澡時靈光一閃,突然想明白了這不只是使用了Reactor(反應時同步時間分派)模式嗎。在這裡寫篇部落格跟大家分享一些拙見。 先貼一下之前看得不

認識函式的同步非同步

1.同步 #引用時間片段,系統 import time import os #同步程序阻塞 def rep_a(): print("開始請求處理rep_a"); time.sleep(5) print("完成處理rep_a");

python併發程式設計之多程序多執行緒非同步

一、多執行緒   多執行緒就是允許一個程序記憶體在多個控制權,以便讓多個函式同時處於啟用狀態,從而讓多個函式的操作同時執行。即使是單CPU的計算機,也可以通過不停地在不同執行緒的指令間切換,從而造成多執行緒同時執行的效果。   多執行緒相當於一個併發(concunrr

Python 中的進同步異步回調(一)

互聯網 科技 編程 一、上下文切換技術簡述在進一步之前,讓我們先回顧一下各種上下文切換技術。不過首先說明一點術語。當我們說“上下文”的時候,指的是程序在執行中的一個狀態。通常我們會用調用棧來表示這個狀態——棧記載了每個調用層級執行到哪裏,還有執行時的環境情況等所有有關的信息。當我們說“上下文切換”

為你揭秘 Python 中的進同步異步回調

運維 互聯網 web 進程和線程究竟是什麽東西?傳統網絡服務模型是如何工作的?協程和線程的關系和區別有哪些?IO 過程在什麽時間發生?一、我們來介紹一下上下文切換技術關於一些術語。當我們說“上下文”的時候,指的是程序在執行中的一個狀態。通常我們會調用棧來表示這個狀態。棧——記載了每個調用層級執行了

Python37 阻塞IO非阻塞IO同步IO異步IO

python協成又稱為微線程CPU是無法識別協程的,只能識別是線程,協成是由開發人員自己控制的。協成可以在單線程下實現並發的效果(實際計算還是串行的方式)。 如果使用線程在多個函數之間進行上下文切換,那麽這個上下文的邏輯位置是保存在CPU中的,而協程也有上下文切換的操作,但是協成的上下文邏輯位置不是通過CPU

python 64式: 第4式eventlet實現併發

#!/usr/bin/env python # -*- coding: utf-8 -*- from datetime import datetime import eventlet eventlet.monkey_patch(all=True) from eventlet.green

非同步+回撥機制執行緒queue執行緒Event單執行緒實現遇到IO切換

# from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor # import requests # import os # import time # import random # # def get(

解釋同步\非同步阻塞\非阻塞並行\併發之間的區別

一、同步:執行一個操作之後,等待結果,然後才繼續執行後續的操作。非同步:執行一個操作後,可以去執行其他的操作,然後等待通知再回來執行剛才沒執行完的操作。 同步和非同步關注的是訊息通訊機制,所謂同步,就是在發出一個呼叫時,在沒有得到結果之前,該呼叫就不返回,但是一旦呼叫返回,

非同步回撥事件驅動概念辨析

同步和非同步: 面試問題什麼是非同步非阻塞 A. 同步 所謂同步,就是在發出一個功能呼叫時,在沒有得到結果之前,該呼叫就不返回。 B. 非同步 非同步的概念和同步相對。 當一個非同步過程呼叫發出後,先返回,呼叫者不會立刻得到結果。 實際處理這個呼叫的部件是在呼叫發出後, 通過狀態、通知來通知