本文經原作者同意後進行轉載和翻譯,原文鏈接
本人正在學習Openstack源碼,爲了自己學習和他人學習方便,故可能將一些國外優秀博客翻譯轉載。本人看英語文章基本順利,但是翻譯卻不太在行,也希望通過這個方式提升一下英語水平,如果您發現我翻譯後的文章問題太嚴重,儘管指出,謝謝!另外也希望志同道合的朋友一起探討有關Openstack的問題!
作爲 核心開發者 ,我已經爲 Openstack 的 Nova 項目工作了18個月多。開始的時候這個項目很小,所以你可以很容易的從代碼庫找到你想要的東西。你的代碼不必完全遵守 PEP8 即可提交。但是,對於任何一個項目來說,隨着項目的深入,更多瑣碎的問題將接踵而來。嚴格控制異常處理、併發、狀態管理、同步異步操作及數據分區變得至關重要。作爲核心開發者也越來越難以記住所有的規則,更不用說是一個新的貢獻者,所以新的貢獻者很難完成第一次提交。
出於這個原因,我想我會在我博客中寫一些深入介紹Openstack項目的文章,幫助一些人少走彎路。在這開始,我需要先介紹一下Openstack源碼佈局和基礎架構。
我將假設你懂得 Cloud IaaS (鏡像管理、虛擬機管理器、實例管理、網絡管理等概念), Python (如果你是經驗豐富的程序員,語言不是問題)還有基於事件驅動的框架(又叫做 Reactor pattern )。
源碼佈局
在你一拿到Nova的源碼後,你會很容易的瞭解它的主要佈局。
git clone https://github.com/openstack/nova.git 真正的Nova服務的代碼在 ./nova 下,相應的單元測試在 ./nova/tests 下。這是一個簡化的Nova源碼目錄結構:
├── etc
│ └── nova
├── nova
│ ├── api - the Nova HTTP service
│ │ ├── ec2 - the Amazon EC2 API bindings
│ │ ├── metadata
│ │ └── openstack - the OpenStack API
│ ├── auth - authentication libraries
│ ├── common - shared Nova components
│ ├── compute - the Nova Compute service
│ ├── console - instance console library
│ ├── db - database abstraction
│ │ └── sqlalchemy
│ │ └── migrate_repo
│ │ └── versions - Schema migrations for SqlAlchemy
│ ├── network - the Nova Network service
│ ├── notifier - event notification library
│ ├── openstack - ongoing effort to reuse Nova parts with other OpenStack parts.
│ │ └── common
│ ├── rpc - Remote Procedure Call libraries for Nova Services
│ ├── scheduler - Nova Scheduler service
│ ├── testing
│ │ └── fake - “Fakes” for testing
│ ├── tests - Unit tests. Sub directories should mirror ./nova
│ ├── virt - Hypervisor abstractions
│ ├── vnc - VNC libraries for accessing Windows instances
│ └── volume - the Volume service
├── plugins - hypervisor host plugins. Mostly for XenServer.
深入看代碼前,我們需要仔細瞭解Nova的架構。Openstack是多個服務的集合,一個服務意味着運行着的一個進程。根據部署Openstack的規模,決定了你是選擇將所有服務運行在同一個機器上還是多個機器上。
Openstack的核心服務爲: API、Compute、Scheduler和Network。你也可能需要管理主機鏡像(可存儲在 Swift Storage Service )的 Glance Image Service 。我們會在之後深入瞭解每一個服務,但是現在需要了解他們各自的任務是什麼。 API是進入Nova的HTTP接口。Compute和虛擬機管理器交互來運行虛擬機(經常是一個主機一個Compute服務)。Network通過和交換機、路由器、防火牆以及相關設備來管理Ip地址池。Scheduler從可用池中選擇最合適的計算節點來創建新的實例(它也可能用來選擇Volumes)。
數據庫本身不是Nova的服務之一。每一個Nova服務都可以直接訪問數據庫(儘管它不應該這樣訪問,我們正在修正這個問題)。如果一個計算節點被攻擊,我們要避免它來訪問數據庫。
你可能單獨的運行一個 Authentication 服務(像Kenstone) 或者負責管理硬盤的 Volume 服務,這都不是必須的。
Openstack Nova 使用 AMQP (特別是 RabbitMQ ) 作爲服務之間的交流總線。AMQP 信息寫入到專門的隊列中,然後由專門的服務從中去走進行處理。這個決定了Nova的性能。如果你發現一個單一的計算節點不能處理所有的請求,你可以增加另外一個計算節點,其他服務也可以這麼做。
如果AMQP是服務之間唯一的交互方式,那麼用戶如何執行指令?答案是API服務,它是一個HTTP服務(一個Python中的 WSGI 應用)。API服務監聽HTTP上的 REST 命令並且將他們轉換成相應服務的AMQP消息。同樣的,來自服務的相應也通過 AMQP和API服務轉換成HTTP相應返回給請求者。 OpenStack當前可以使用 EC2 (亞馬遜API) 和 OpenStack (是 Rackspace API 的變種)。我們將在後面的文章中詳細介紹API服務。
但是不僅僅是API可以和服務交互。服務之間也可以交互。Compute可能需要和Network和Volume交互來獲得必須的資源。如果我們不關心怎麼組織源碼,這些功能會是代碼有一點點凌亂。現在,我們開始深入瞭解服務和RPC機制。
註釋
我將使用Python的單元測試模塊,方法以及函數。特別的,nova.compute.api:API.runinstance 等同與 ./nova/compute/api.py文件中的runinstance方法。同樣的,nova.compute.api.dosomething指的是./nova/compute/api.py文件中的dosomething函數。
和一個服務交互
除了API服務,每一個Nova服務必須有一個相應的Python模塊來處理RPC命令的封裝處理。例如:
Network服務 ./nova/network/api.py Compute服務 ./nova/compute/api.py Scheduler服務 ./nova/scheduler/api.py … 這些模塊通過集合大量函數來使服務正常工作。但是有的時候他們包含一些類來工作。這都依賴與我們是否需要截斷一些服務對函數的調用。我們會在接下來接觸這些用例。
Scheduler服務nova.scheduler.api可能有着最多的簡單接口,包含最難的函數。
Network是一個有着唯一API類的服務,儘管它可以通過簡單的函數被實現。
Compute有一個有趣的類層封裝,如:
BaseAPI->API->AggregateAPI BaseAPI->HostAPI nova.compute.api.API 是類中的主力,我們將在以後做別的派生。
如果我想要暫停一個運行中的實例,我需要導入nova.compute.api,實例化API類並且調用pause()方法。這個過程將封裝參數並且將它傳送給Compute服務,由Compute通過相應的AMQP隊列來管理那個實例。尋找相應的compute服務的AMQP是通過一個數據庫的快速掃描實現的,這個方法在nova.compute.api:BaseAPI.castorcallcompute_message。對與其他服務也是這樣,通過調用相應的api模塊然後調用函數。
Cast和Call
AMQP不是完全的 RPC 機制,但是我們可以從它那裏獲得類RPC特性。在nova.rpc.init中有兩個調用來操作cast()和call()。cast()在一個服務上執行異步的調用,而call()是一個同步的操作所以它需要一個返回值。call()真正做的是從服務動態創建一個短暫的AMQP來返回消息。它會一直等待一個 eventlet greenthread 直到接收到響應。
如果異常是源於nova.exception:NovaException的,那麼它也可以通過這個響應傳遞以及在調用者方重生成/重拋出。否則,一個nova.rpc.common:RemoteError會被拋出。
理論上,我們將僅僅執行異步cast()來和服務通信,而call()很明耗費更大的代價。認真選擇你需要的,如果可能,儘量不要依賴返回值。同時,儘量使你的函數是冪等的,因爲它們可能會在未來一直執行。
如果你對rpc-over-amqp的工作原理感興趣,多看看nova.rpc.impl_kombu
Fail-Fast 系統架構
Openstack使用的是“快速失敗”的系統架構。如果一個請求不成功,則馬上返回一個一場丟給其調用者。但是,當一個Nova服務是eventlet中的一個操作時,它一般不會以我們希望的狀態終止任何進程或離開系統。一個新的請求可以通過AMQP或HTTP非常容易的被處理。除非我們正在做的一件事情需要顯示的進行清理。如果你期望字典中一個確定的值,一個關鍵錯誤彈出是正確的。對於不同的錯誤情況,你不需要常常派生一個獨立的異常,甚至在最壞的情況下,WSGI中間件將把它轉化成客戶端可以處理的。對於事件驅動的編程這是很不錯的方式,我們會在後續的文章中講解nova的錯誤處理。
好了,這是一些Nova源碼的佈局和服務間如何通訊。下一此我們將探究服務管理器和驅動,來了解服務如何在被調用方實現。
轉自:http://yansu.org/2012/11/08/openstack-nova-internal.html