Python網路程式設計 8 快取與訊息佇列
阿新 • • 發佈:2019-01-29
前面已經介紹了套接字API以及在Python中使用的基礎IP網路操作來構建通訊通道的方式。本章研究服務負載較重時常用的兩項基本技術:快取與訊息佇列。這兩項技術有如下一些共同特點:
- 都是非常強大的工具,因而廣為流行。使用Memcached或一個訊息佇列,不是為了實現一個有趣的協議來與其他工具進行互動,二是為了編寫優雅的服務來解決特定的問題。
- 這兩項技術解決的問題通常是機構內部特有的問題。我們通常無法僅從外界就得知一個特定的網站或網路服務使用了哪種快取、哪種訊息佇列以及哪種負載分配工具。
- 儘管HTTP和SMTP這樣的工具都是針對一個特定的負載設計的(HTTP針對超文字文件,SMTP針對電子郵件訊息),但是快取和訊息佇列是無需瞭解它們所要傳輸的資料的。
- 我們可以將快取和訊息佇列視為提供了兩個已經造好的輪子,以避免重複的勞動。
- 在每臺擁有空閒記憶體的伺服器上都執行一個Memcached守護程序。
- 將所有Memcached守護程序的IP地址與埠號列出,並將該列表傳送給所有將要使用Memcached的客戶端。
- 客戶端程式現在可以訪問一個組織級的速度極快的鍵值快取,它就像是所有伺服器之間共享的一個巨大的Python字典。該快取是基於LRU的。如果有些項長時間沒有被訪問的話,就會將這些項丟棄,為新訪問的項挪出空間,並記錄被頻繁訪問的項。
- Memcached的介面和Python的字典極其類似。將一個字串作為值傳入set()時,該字串會以utf-8編碼直接被寫入Memcached,稍後在通過get()獲取該字串時會進行解碼。除了簡單字串之外,寫入任何其他Python物件都會自動觸發memcache模組的pickle操作,然後將二進位制的pickle儲存在Memcached中。要牢記這一不同點,因為有時我們編寫的Python應用程式會與用其他語言寫的客戶端共享Memcached快取,此時,只有一字串形式儲存的值才可以被使用其他語言編寫的客戶端直接使用。
- 伺服器是可以丟棄儲存在Memcached中的資料的。Memcached的目的是將重複計算花銷較高的結果記錄下來,以此來加速操作。它不是用來作為資料的唯一儲存區的!
- 當Memcached客戶端得到了包含多個Memcached例項的列表時,會根據每個鍵的字串的雜湊值對Memcached資料庫進行分割槽(shard),由計算出的雜湊值決定用Memcached叢集中的哪臺伺服器來儲存特定的記錄。
- 當使用電子郵箱地址在網站註冊賬號時,通常會立刻返回一個頁面,請於郵件收件箱內查收確認郵件。在這一過程中,使用者無需等待,而網站通過我們的電子郵箱服務提供商傳輸郵件則可能需要好幾分鐘的時間。網站的通常做法是將電子郵箱地址放在一個訊息佇列裡,當後臺伺服器準備好建立一個用於傳送的SMTP連線時,就會從訊息佇列中獲取郵箱地址。如果傳送暫時失敗,那麼電子郵箱地址會被直接放回到佇列中,在經歷更長的時間間隔後重試。
- 管道(pipeline)拓撲結構可能是與我們腦海中對於佇列的直觀映像最相似的一種模式:生產者建立訊息,然後將訊息提交至佇列中,消費者從佇列中接收訊息。例如,一個照片分享網站的前端網路伺服器可能會將使用者上傳的圖片儲存在一個專門用於接收檔案的內部佇列中。包含許多縮圖生成工具的機房會從佇列中讀取圖片。每個影象處理伺服器每次從佇列中接收一條訊息(訊息中包含需要生成縮圖的圖片),然後為其生成縮圖。站點較為繁忙時,佇列在執行過程中可能會越來越長;站點較為空閒時,佇列就會變短或是再次清空。不過,無論站點是否繁忙,前端網路伺服器都可以直接向等待的客戶端返回一個響應,告訴使用者,上傳已經成功,並且很快就能在他們的照片流中看到。
- 釋出者-訂閱者(publisher-subscriber)或扇出(fanout)結構看上去和管道結構差不多,不過二者有一個重要的區別。雖然管道結構的訊息佇列能夠保證佇列中的沒個訊息都會被髮送給一個消費者(這是由於,把同一張圖片傳送給兩臺影象伺服器畢竟是很浪費的),但是訊息訂閱者通常想要接收佇列中的所有訊息。因此另一種方法是,由訂閱者設定一個過濾器,通過某種特定的格式限定有興趣的訊息範圍。該型別的佇列可以用於需要向外部世界推送事件的外部服務。伺服器機房同樣可以使用佇列系統來對哪些系統啟動了,哪些系統因為維護而關閉進行通知。除此之外,甚至還可以使用這種佇列系統在其他訊息佇列建立和銷燬的時候釋出他們的地址。
- 最後一個是請求-響應(request-reply)模式,這也是最為複雜的模式。複雜的原因在於訊息需要進行往返。在前面兩種模式中,訊息生產者的工作是非常少的。生產者連線到佇列,然後傳送訊息,僅此而已。但是,發起請求的訊息佇列客戶端需要保持連線,並等待接收響應。為了支援這一點,佇列必須提供某種定址機制,從成百上千個已經連線並且仍然處於等待的客戶端中找到正確的客戶端,將響應傳送到該客戶端。不過也正是由於這一複雜性使得請求-響應模式幾乎成為了最強大的模式。它允許我們將幾十或是幾百個客戶端請求均勻分佈到大量伺服器中,除了設定訊息佇列外,不需要做其它任何工作。一個優秀的訊息佇列允許伺服器在不丟失訊息的前提下繫結到訊息佇列或解除繫結,因此這種拓撲結構的訊息佇列同樣允許伺服器在需要維護而關閉時的行為對客戶端機器保持不可見。