打開浏覽器,輸入位址,按下回車,打開了頁面。于是一個<code>HTTP</code>請求(<code>request</code>)就由用戶端發送到伺服器,伺服器處理請求,傳回響應(<code>response</code>)内容。
我們每天都在浏覽網頁,發送大大小小的請求給伺服器。有時候,伺服器接到了請求,會發現他也需要給另外的伺服器發送請求,或者伺服器也需要做另外一些事情,于是最初們發送的請求就被阻塞了,也就是要等待伺服器完成其他的事情。
更多的時候,伺服器做的額外事情,并不需要用戶端等待,這時候就可以把這些額外的事情異步去做。從事異步任務的工具有很多。主要原理還是處理通知消息,針對通知消息通常采取是隊列結構。生産和消費消息進行通信和業務實作。
上述異步任務的實作,可以抽象為生産者消費模型。如同一個餐館,廚師在做飯,吃貨在吃飯。如果廚師做了很多,暫時賣不完,廚師就會休息;如果客戶很多,廚師馬不停蹄的忙碌,客戶則需要慢慢等待。實作生産者和消費者的方式用很多,下面使用<code>Python</code>标準庫<code>Queue</code>寫個小例子:
大概輸出如下:
Python内置了一個好用的隊列結構。我們也可以是用redis實作類似的操作。并做一個簡單的異步任務。
Redis提供了兩種方式來作消息隊列。一個是使用<code>生産者消費模式</code>模式,另外一個方法就是<code>釋出訂閱者模式</code>。前者會讓一個或者多個用戶端監聽消息隊列,一旦消息到達,消費者馬上消費,誰先搶到算誰的,如果隊列裡沒有消息,則消費者繼續監聽。後者也是一個或多個用戶端訂閱消息頻道,隻要釋出者釋出消息,所有訂閱者都能收到消息,訂閱者都是ping的。
主要使用了redis提供的blpop擷取隊列資料,如果隊列沒有資料則阻塞等待,也就是監聽。
使用redis的pubsub功能,訂閱者訂閱頻道,釋出者釋出消息到頻道了,頻道就是一個消息隊列。
我們分别實作了兩種異步任務的後端服務,直接啟動他們,就能監聽redis隊列或頻道的消息了。簡單的測試如下:
啟動腳本,使用
可以分别在監聽的腳本輸入中看到異步消息。在異步的任務中,可以執行一些耗時間的操作,當然目前這些做法并不知道異步的執行結果,如果需要知道異步的執行結果,可以考慮設計協程任務或者使用一些工具如<code>RQ</code>或者<code>celery</code>等。