Google App Engine技術(shù)架構(gòu)資料大盤點(diǎn)
今天看到幾篇有關(guān)Google App Engine的技術(shù)架構(gòu)文章,一起分享給大家,沒看到過的同學(xué)趕緊驚喜一下吧,看到過了的同學(xué)也假裝驚喜一下嘛,呵呵。
全部文章有點(diǎn)長,請(qǐng)耐心看下去,相信程序員都是有耐心的,除了我.......
一、Google的核心技術(shù)
在切入Google App Engine之前,首先會(huì)對(duì)Google的核心技術(shù)和其整體架構(gòu)進(jìn)行分析,以幫助大家之后更好地理解Google App Engine的實(shí)現(xiàn)。
本篇將主要介紹Google的十個(gè)核心技術(shù),而且可以分為四大類:
◆ 分布式基礎(chǔ)設(shè)施:GFS、Chubby 和 Protocol Buffer。
◆ 分布式大規(guī)模數(shù)據(jù)處理:MapReduce 和 Sawzall。
◆ 分布式數(shù)據(jù)庫技術(shù):BigTable 和數(shù)據(jù)庫 Sharding。
◆ 數(shù)據(jù)中心優(yōu)化技術(shù):數(shù)據(jù)中心高溫化、12V電池和服務(wù)器整合。
分布式基礎(chǔ)設(shè)施
GFS
由于搜索引擎需要處理海量的數(shù)據(jù),所以Google的兩位創(chuàng)始人Larry Page和Sergey Brin在創(chuàng)業(yè)初期設(shè)計(jì)一套名為"BigFiles"的文件系統(tǒng),而GFS(全稱為"Google File System")這套分布式文件系統(tǒng)則是"BigFiles"的延續(xù)。
首先,介紹它的架構(gòu),GFS主要分為兩類節(jié)點(diǎn):
◆ Master節(jié)點(diǎn):主要存儲(chǔ)與數(shù)據(jù)文件相關(guān)的元數(shù)據(jù),而不是Chunk(數(shù)據(jù)塊)。元數(shù)據(jù)包括一個(gè)能將64位標(biāo)簽映射到數(shù)據(jù)塊的位置及其組成文件 的表格,數(shù)據(jù)塊副本位置和哪個(gè)進(jìn)程正在讀寫特定的數(shù)據(jù)塊等。還有Master節(jié)點(diǎn)會(huì)周期性地接收從每個(gè)Chunk節(jié)點(diǎn)來的更新("Heart- beat")來讓元數(shù)據(jù)保持***狀態(tài)。
◆ Chunk節(jié)點(diǎn):顧名思義,肯定用來存儲(chǔ)Chunk,數(shù)據(jù)文件通過被分割為每個(gè)默認(rèn)大小為64MB的Chunk的方式存儲(chǔ),而且每個(gè)Chunk有唯一一個(gè)64位標(biāo)簽,并且每個(gè)Chunk都會(huì)在整個(gè)分布式系統(tǒng)被復(fù)制多次,默認(rèn)為3次。
下圖就是GFS的架構(gòu)圖:

圖1. GFS的架構(gòu)圖(參片[15])
接著,在設(shè)計(jì)上,GFS主要有八個(gè)特點(diǎn):
◆ 大文件和大數(shù)據(jù)塊:數(shù)據(jù)文件的大小普遍在GB級(jí)別,而且其每個(gè)數(shù)據(jù)塊默認(rèn)大小為64MB,這樣做的好處是減少了元數(shù)據(jù)的大小,能使Master節(jié)點(diǎn)能夠非常方便地將元數(shù)據(jù)放置在內(nèi)存中以提升訪問效率。
◆ 操作以添加為主:因?yàn)槲募苌俦粍h減或者覆蓋,通常只是進(jìn)行添加或者讀取操作,這樣能充分考慮到硬盤線性吞吐量大和隨機(jī)讀寫慢的特點(diǎn)。
◆ 支持容錯(cuò):首先,雖然當(dāng)時(shí)為了設(shè)計(jì)方便,采用了單Master的方案,但是整個(gè)系統(tǒng)會(huì)保證每個(gè)Master都會(huì)有其相對(duì)應(yīng)的復(fù)制品,以便于在 Master節(jié)點(diǎn)出現(xiàn)問題時(shí)進(jìn)行切換。其次,在Chunk層,GFS已經(jīng)在設(shè)計(jì)上將節(jié)點(diǎn)失敗視為常態(tài),所以能非常好地處理Chunk節(jié)點(diǎn)失效的問題。
◆ 高吞吐量:雖然其單個(gè)節(jié)點(diǎn)的性能無論是從吞吐量還是延遲都很普通,但因?yàn)槠渲С稚锨У墓?jié)點(diǎn),所以總的數(shù)據(jù)吞吐量是非常驚人的。
◆ 保護(hù)數(shù)據(jù):首先,文件被分割成固定尺寸的數(shù)據(jù)塊以便于保存,而且每個(gè)數(shù)據(jù)塊都會(huì)被系統(tǒng)復(fù)制三份。
◆ 擴(kuò)展能力強(qiáng):因?yàn)樵獢?shù)據(jù)偏小,使得一個(gè)Master節(jié)點(diǎn)能控制上千個(gè)存數(shù)據(jù)的Chunk節(jié)點(diǎn)。
◆ 支持壓縮:對(duì)于那些稍舊的文件,可以通過對(duì)它進(jìn)行壓縮,來節(jié)省硬盤空間,并且壓縮率非常驚人,有時(shí)甚至接近90%。
◆ 用戶空間:雖然在用戶空間運(yùn)行在運(yùn)行效率方面稍差,但是更便于開發(fā)和測試,還有能更好利用Linux的自帶的一些POSIX API。
現(xiàn)在Google內(nèi)部至少運(yùn)行著200多個(gè)GFS集群,***的集群有幾千臺(tái)服務(wù)器,并且服務(wù)于多個(gè)Google服務(wù),比如Google搜索。但由于 GFS主要為搜索而設(shè)計(jì),所以不是很適合新的一些Google產(chǎn)品,比YouTube、Gmail和更強(qiáng)調(diào)大規(guī)模索引和實(shí)時(shí)性的Caffeine搜索引擎 等,所以Google已經(jīng)在開發(fā)下一代GFS,代號(hào)為"Colossus",并且在設(shè)計(jì)方面有許多不同,比如:支持分布式Master節(jié)點(diǎn)來提升高可用性 并能支撐更多文件,Chunk節(jié)點(diǎn)能支持1MB大小的chunk以支撐低延遲應(yīng)用的需要。
Chubby
簡單的來說,Chubby 屬于分布式鎖服務(wù),通過 Chubby,一個(gè)分布式系統(tǒng)中的上千個(gè)client都能夠?qū)τ谀稠?xiàng)資源進(jìn)行"加鎖"或者"解鎖",常用于BigTable的協(xié)作工作,在實(shí)現(xiàn)方面是通過 對(duì)文件的創(chuàng)建操作來實(shí)現(xiàn)"加鎖",并基于著名科學(xué)家Leslie Lamport的Paxos算法。
Protocol Buffer
Protocol Buffer,是Google內(nèi)部使用一種語言中立、平臺(tái)中立和可擴(kuò)展的序列化結(jié)構(gòu)化數(shù)據(jù)的方式,并提供 Java、C++ 和 Python 這三種語言的實(shí)現(xiàn),每一種實(shí)現(xiàn)都包含了相應(yīng)語言的編譯器以及庫文件,而且它是一種二進(jìn)制的格式,所以其速度是使用 XML 進(jìn)行數(shù)據(jù)交換的10倍左右。它主要用于兩個(gè)方面:其一是RPC通信,它可用于分布式應(yīng)用之間或者異構(gòu)環(huán)境下的通信。其二是數(shù)據(jù)存儲(chǔ)方面,因?yàn)樗悦枋觯?且壓縮很方便,所以可用于對(duì)數(shù)據(jù)進(jìn)行持久化,比如存儲(chǔ)日志信息,并可被Map Reduce程序處理。與Protocol Buffer比較類似的產(chǎn)品還有Facebook的 Thrift ,而且 Facebook 號(hào)稱Thrift在速度上還有一定的優(yōu)勢(shì)。
分布式大規(guī)模數(shù)據(jù)處理
MapReduce
首先,在Google數(shù)據(jù)中心會(huì)有大規(guī)模數(shù)據(jù)需要處理,比如被網(wǎng)絡(luò)爬蟲(Web Crawler)抓取的大量網(wǎng)頁等。由于這些數(shù)據(jù)很多都是PB級(jí)別,導(dǎo)致處理工作不得不盡可能的并行化,而Google為了解決這個(gè)問題,引入了 MapReduce這個(gè)編程模型,MapReduce是源自函數(shù)式語言,主要通過"Map(映射)"和"Reduce(化簡)"這兩個(gè)步驟來并行處理大規(guī) 模的數(shù)據(jù)集。Map會(huì)先對(duì)由很多獨(dú)立元素組成的邏輯列表中的每一個(gè)元素進(jìn)行指定的操作,且原始列表不會(huì)被更改,會(huì)創(chuàng)建多個(gè)新的列表來保存Map的處理結(jié) 果。也就意味著,Map操作是高度并行的。當(dāng)Map工作完成之后,系統(tǒng)會(huì)先對(duì)新生成的多個(gè)列表進(jìn)行清理(Shuffle)和排序,之后會(huì)這些新創(chuàng)建的列表 進(jìn)行Reduce操作,也就是對(duì)一個(gè)列表中的元素根據(jù)Key值進(jìn)行適當(dāng)?shù)暮喜ⅰ?/P>
下圖為MapReduce的運(yùn)行機(jī)制:
圖2. MapReduce的運(yùn)行機(jī)制(參[19])
接下來,將根據(jù)上圖來舉一個(gè)MapReduce的例子:比如,通過搜索Spider將海量的Web頁面抓取到本地的GFS集群中,然后Index系 統(tǒng)將會(huì)對(duì)這個(gè)GFS集群中多個(gè)數(shù)據(jù)Chunk進(jìn)行平行的Map處理,生成多個(gè)Key為URL,value為html頁面的鍵值對(duì)(Key-Value Map),接著系統(tǒng)會(huì)對(duì)這些剛生成的鍵值對(duì)進(jìn)行Shuffle(清理),之后系統(tǒng)會(huì)通過Reduce操作來根據(jù)相同的key值(也就是URL)合并這些鍵 值對(duì)。
***,通過MapReduce這么簡單的編程模型,不僅能用于處理大規(guī)模數(shù)據(jù),而且能將很多繁瑣的細(xì)節(jié)隱藏起來,比如自動(dòng)并行化,負(fù)載均衡和機(jī)器宕 機(jī)處理等,這樣將極大地簡化程序員的開發(fā)工作。MapReduce可用于包括"分布grep,分布排序,web訪問日志分析,反向索引構(gòu)建,文檔聚類,機(jī) 器學(xué)習(xí),基于統(tǒng)計(jì)的機(jī)器翻譯,生成Google的整個(gè)搜索的索引"等大規(guī)模數(shù)據(jù)處理工作。Yahoo也推出MapReduce的開源版本Hadoop,而 且Hadoop在業(yè)界也已經(jīng)被大規(guī)模使用。
Sawzall
Sawzall可以被認(rèn)為是構(gòu)建在MapReduce之上的采用類似Java語法的DSL(Domain-Specific Language),也可以認(rèn)為它是分布式的AWK。它主要用于對(duì)大規(guī)模分布式數(shù)據(jù)進(jìn)行篩選和聚合等高級(jí)數(shù)據(jù)處理操作,在實(shí)現(xiàn)方面,是通過解釋器將其轉(zhuǎn)化 為相對(duì)應(yīng)的MapReduce任務(wù)。除了Google的Sawzall之外,yahoo推出了相似的Pig語言,但其語法類似于SQL。
分布式數(shù)據(jù)庫技術(shù)
BigTable
由于在Google的數(shù)據(jù)中心存儲(chǔ)PB級(jí)以上的非關(guān)系型數(shù)據(jù)時(shí)候,比如網(wǎng)頁和地理數(shù)據(jù)等,為了更好地存儲(chǔ)和利用這些數(shù)據(jù),Google開發(fā)了一套數(shù) 據(jù)庫系統(tǒng),名為"BigTable"。BigTable不是一個(gè)關(guān)系型的數(shù)據(jù)庫,它也不支持關(guān)聯(lián)(Join)等高級(jí)SQL操作,取而代之的是多級(jí)映射的數(shù) 據(jù)結(jié)構(gòu),并是一種面向大規(guī)模處理、容錯(cuò)性強(qiáng)的自我管理系統(tǒng),擁有TB級(jí)的內(nèi)存和PB級(jí)的存儲(chǔ)能力,使用結(jié)構(gòu)化的文件來存儲(chǔ)數(shù)據(jù),并每秒可以處理數(shù)百萬的讀 寫操作。
什么是多級(jí)映射的數(shù)據(jù)結(jié)構(gòu)呢?就是一個(gè)稀疏的,多維的,排序的Map,每個(gè)Cell由行關(guān)鍵字,列關(guān)鍵字和時(shí)間戳三維定位.Cell的內(nèi)容是一個(gè)不 解釋的字符串,比如下表存儲(chǔ)每個(gè)網(wǎng)站的內(nèi)容與被其他網(wǎng)站的反向連接的文本。 反向的URL com.cnn.www是這行的關(guān)鍵字;contents列存儲(chǔ)網(wǎng)頁內(nèi)容,每個(gè)內(nèi)容有一個(gè)時(shí)間戳,因?yàn)橛袃蓚€(gè)反向連接,所以archor的Column Family有兩列:anchor: cnnsi.com和anchhor:my.look.ca。Column Family這個(gè)概念,使得表可以輕松地橫向擴(kuò)展。下面是它具體的數(shù)據(jù)模型圖:
圖3. BigTable數(shù)據(jù)模型圖(參[4])
在結(jié)構(gòu)上,首先,BigTable基于GFS分布式文件系統(tǒng)和Chubby分布式鎖服務(wù)。其次BigTable也分為兩部分:其一是Master節(jié) 點(diǎn),用來處理元數(shù)據(jù)相關(guān)的操作并支持負(fù)載均衡。其二是tablet節(jié)點(diǎn),主要用于存儲(chǔ)數(shù)據(jù)庫的分片tablet,并提供相應(yīng)的數(shù)據(jù)訪問,同時(shí)Tablet 是基于名為SSTable的格式,對(duì)壓縮有很好的支持。
圖4. BigTable架構(gòu)圖(參[15])
BigTable正在為Google六十多種產(chǎn)品和項(xiàng)目提供存儲(chǔ)和獲取結(jié)構(gòu)化數(shù)據(jù)的支撐平臺(tái),其中包括有Google Print、 Orkut、Google Maps、Google Earth和Blogger等,而且Google至少運(yùn)行著500個(gè)BigTable集群。
隨著Google內(nèi)部服務(wù)對(duì)需求的不斷提高和技術(shù)的不斷地發(fā)展,導(dǎo)致原先的BigTable已經(jīng)無法滿足用戶的需求,而Google也正在開發(fā)下一代BigTable,名為"Spanner(扳手)",它主要有下面這些BigTable所無法支持的特性:
◆ 支持多種數(shù)據(jù)結(jié)構(gòu),比如table,familie,group和coprocessor等。
◆ 基于分層目錄和行的細(xì)粒度的復(fù)制和權(quán)限管理。
◆ 支持跨數(shù)據(jù)中心的強(qiáng)一致性和弱一致性控制。
◆ 基于Paxos算法的強(qiáng)一致性副本同步,并支持分布式事務(wù)。
◆ 提供許多自動(dòng)化操作。
◆ 強(qiáng)大的擴(kuò)展能力,能支持百萬臺(tái)服務(wù)器級(jí)別的集群。
◆ 用戶可以自定義諸如延遲和復(fù)制次數(shù)等重要參數(shù)以適應(yīng)不同的需求。
數(shù)據(jù)庫Sharding
Sharding就是分片的意思,雖然非關(guān)系型數(shù)據(jù)庫比如BigTable在Google的世界中占有非常重要的地位,但是面對(duì)傳統(tǒng)OLTP應(yīng)用, 比如廣告系統(tǒng),Google還是采用傳統(tǒng)的關(guān)系型數(shù)據(jù)庫技術(shù),也就是MySQL,同時(shí)由于Google所需要面對(duì)流量非常巨大,所以Google在數(shù)據(jù)庫 層采用了分片(Sharding)的水平擴(kuò)展(Scale Out)解決方案,分片是在傳統(tǒng)垂直擴(kuò)展(Scale Up)的分區(qū)模式上的一種提升,主要通過時(shí)間,范圍和面向服務(wù)等方式來將一個(gè)大型的數(shù)據(jù)庫分成多片,并且這些數(shù)據(jù)片可以跨越多個(gè)數(shù)據(jù)庫和服務(wù)器來實(shí)現(xiàn)水平 擴(kuò)展。
Google整套數(shù)據(jù)庫分片技術(shù)主要有下面這些優(yōu)點(diǎn):
◆ 擴(kuò)展性強(qiáng):在Google生產(chǎn)環(huán)境中,已經(jīng)有支持上千臺(tái)服務(wù)器的MySQL分片集群。
◆ 吞吐量驚人:通過巨大的MySQL分片集群能滿足巨量的查詢請(qǐng)求。
◆ 全球備份:不僅在一個(gè)數(shù)據(jù)中心還是在全球的范圍,Google都會(huì)對(duì)MySQL的分片數(shù)據(jù)進(jìn)行備份,這樣不僅能保護(hù)數(shù)據(jù),而且方便擴(kuò)展。
在實(shí)現(xiàn)方面,主要可分為兩塊:其一是在MySQL InnoDB基礎(chǔ)上添加了數(shù)據(jù)庫分片的技術(shù)。其二是在ORM層的Hibernate的基礎(chǔ)上也添加了相關(guān)的分片技術(shù),并支持虛擬分片(Virtual Shard)來便于開發(fā)和管理。同時(shí)Google也已經(jīng)將這兩方面的代碼提交給相關(guān)組織。
數(shù)據(jù)中心優(yōu)化技術(shù)
數(shù)據(jù)中心高溫化
大中型數(shù)據(jù)中心的PUE(Power Usage Effectiveness)普遍在2左右,也就是在服務(wù)器等計(jì)算設(shè)備上耗1度電,在空調(diào)等輔助設(shè)備上也要消耗一度電。對(duì)一些非常出色的數(shù)據(jù)中心,最多也 就能達(dá)到1.7,但是Google通過一些有效的設(shè)計(jì)使部分?jǐn)?shù)據(jù)中心到達(dá)了業(yè)界領(lǐng)先的1.2,在這些設(shè)計(jì)當(dāng)中,其中最有特色的莫過于數(shù)據(jù)中心高溫化,也就 是讓數(shù)據(jù)中心內(nèi)的計(jì)算設(shè)備運(yùn)行在偏高的溫度下,Google的能源方面的總監(jiān)Erik Teetzel在談到這點(diǎn)的時(shí)候說:"普通的數(shù)據(jù)中心在70華氏度(21攝氏度)下面工作,而我們則推薦80華氏度(27攝氏度)"。但是在提高數(shù)據(jù)中心 的溫度方面會(huì)有兩個(gè)常見的限制條件:其一是服務(wù)器設(shè)備的崩潰點(diǎn),其二是精確的溫度控制。如果做好這兩點(diǎn),數(shù)據(jù)中心就能夠在高溫下工作,因?yàn)榧僭O(shè)數(shù)據(jù)中心的 管理員能對(duì)數(shù)據(jù)中心的溫度進(jìn)行正負(fù)1/2度的調(diào)節(jié),這將使服務(wù)器設(shè)備能在崩潰點(diǎn)5度之內(nèi)工作,而不是常見的20度之內(nèi),這樣既經(jīng)濟(jì),又安全。還有,業(yè)界傳 言Intel為Google提供抗高溫設(shè)計(jì)的定制芯片,但云計(jì)算界的***專家James Hamilton認(rèn)為不太可能,因?yàn)殡m然處理器也非常懼怕熱量,但是與內(nèi)存和硬盤相比還是強(qiáng)很多,所以處理器在抗高溫設(shè)計(jì)中并不是一個(gè)核心因素。同時(shí)他也 非常支持使數(shù)據(jù)中心高溫化這個(gè)想法,而且期望將來數(shù)據(jù)中心甚至能運(yùn)行在40攝氏度下,這樣不僅能節(jié)省空調(diào)方面的成本,而且對(duì)環(huán)境也很有利。
12V電池
由于傳統(tǒng)的UPS在資源方面比較浪費(fèi),所以Google在這方面另辟蹊徑,采用了給每臺(tái)服務(wù)器配一個(gè)專用的12V電池的做法來替換了常用的UPS, 如果主電源系統(tǒng)出現(xiàn)故障,將由該電池負(fù)責(zé)對(duì)服務(wù)器供電。雖然大型UPS可以達(dá)到92%到95%的效率,但是比起內(nèi)置電池的99.99%而言是非常捉襟見肘 的,而且由于能量守恒的原因,導(dǎo)致那么未被UPS充分利用的電力會(huì)被轉(zhuǎn)化成熱能,這將導(dǎo)致用于空調(diào)的能耗相應(yīng)地攀升,從而走入一個(gè)惡性循環(huán)。同時(shí)在電源方 面也有類似的"神來之筆",普通的服務(wù)器電源會(huì)同時(shí)提供5V和12V的直流電。但是Google設(shè)計(jì)的服務(wù)器電源只輸出12V直流電,必要的轉(zhuǎn)換在主板上 進(jìn)行,雖然這種設(shè)計(jì)會(huì)使主板的成本增加1美元到2美元,但是它不僅能使電源能在接近其峰值容量的情況下運(yùn)行,而且在銅線上傳輸電流時(shí)效率更高。
服務(wù)器整合
談到虛擬化的殺手锏時(shí),***個(gè)讓人想到肯定是服務(wù)器整合,而且普遍能實(shí)現(xiàn)1:8的整合率來降低各方面的成本。有趣的是,Google在硬件方面也引 入類似服務(wù)器整合的想法,它的做法是在一個(gè)機(jī)箱大小的空間內(nèi)放置兩臺(tái)服務(wù)器,這些做的好處有很多,首先,減小了占地面積。其次,通過讓兩臺(tái)服務(wù)器共享諸如 電源等設(shè)備,來降低設(shè)備和能源等方面的投入。
#p#
二、Google App Engine簡介
由于發(fā)布S3和EC2這兩個(gè)優(yōu)秀的云服務(wù),使得Amazon已經(jīng)率先在云計(jì)算市場站穩(wěn)了腳跟,而身為云計(jì)算這個(gè)浪潮的發(fā)起者之一的Google肯定 不甘示弱,并在2008年四月份推出了Google App Engine這項(xiàng)PaaS服務(wù),雖然現(xiàn)在無法稱其為一個(gè)革命性的產(chǎn)品,但肯定是現(xiàn)在市面上最成熟,并且功能最全面的PaaS平臺(tái)。
Google App Engine 提供一整套開發(fā)組件來讓用戶輕松地在本地構(gòu)建和調(diào)試網(wǎng)絡(luò)應(yīng)用,之后能讓用戶在Google強(qiáng)大的基礎(chǔ)設(shè)施上部署和運(yùn)行網(wǎng)絡(luò)應(yīng)用程序,并自動(dòng)根據(jù)應(yīng)用所承受 的負(fù)載來對(duì)應(yīng)用進(jìn)行擴(kuò)展,并免去用戶對(duì)應(yīng)用和服務(wù)器等的維護(hù)工作。同時(shí)提供大量的免費(fèi)額度和靈活的資費(fèi)標(biāo)準(zhǔn)。在開發(fā)語言方面,現(xiàn)支持Java和 Python這兩種語言,并為這兩種語言提供基本相同的功能和API。
功能
在功能上,主要有六個(gè)方面:
◆ 動(dòng)態(tài)網(wǎng)絡(luò)服務(wù),并提供對(duì)常用網(wǎng)絡(luò)技術(shù)的支持,比如SSL等 。
◆ 持久存儲(chǔ)空間,并支持簡單的查詢和本地事務(wù)。
◆ 能對(duì)應(yīng)用進(jìn)行自動(dòng)擴(kuò)展和負(fù)載平衡。
◆ 一套功能完整的本地開發(fā)環(huán)境,可以讓用戶在本機(jī)上對(duì)App Engine進(jìn)行開發(fā)和調(diào)試。
◆ 支持包括Email和用戶認(rèn)證等多種服務(wù)。
◆ 提供能在指定時(shí)間和定期觸發(fā)事件的計(jì)劃任務(wù)和能實(shí)現(xiàn)后臺(tái)處理的任務(wù)隊(duì)列。
使用流程
整個(gè)使用流程主要包括五個(gè)步驟:
◆ 下載SDK和IDE,并在本地搭建開發(fā)環(huán)境。
◆ 在本地對(duì)應(yīng)用進(jìn)行開發(fā)和調(diào)試。
◆ 使用GAE自帶上傳工具來將應(yīng)用部署到平臺(tái)上。
◆ 在管理界面中啟動(dòng)這個(gè)應(yīng)用。
◆ 利用管理界面來監(jiān)控整個(gè)應(yīng)用的運(yùn)行狀態(tài)和資費(fèi)。
由于本系列是專注于GAE的實(shí)現(xiàn)和設(shè)計(jì)兩方面,所以不會(huì)對(duì)GAE的使用有非常深入地介紹,如果希望大家對(duì)GAE的使用方面有更深的理解,具體可以參看一下GAE的官方文檔(http://code.google.com/intl/zh-CN/appengine/docs/whatisgoogleappengine.html)。
Google App Engine的主要組成部分
主要可分為五部分:
◆ 應(yīng)用服務(wù)器:主要是用于接收來自于外部的Web請(qǐng)求。
◆ Datastore:主要用于對(duì)信息進(jìn)行持久化,并基于Google著名的BigTable技術(shù)。
◆ 服務(wù):除了必備的應(yīng)用服務(wù)器和Datastore之外,GAE還自帶很多服務(wù)來幫助開發(fā)者,比如:Memcache,郵件,網(wǎng)頁抓取,任務(wù)隊(duì)列,XMPP等。
◆ 管理界面:主要用于管理應(yīng)用并監(jiān)控應(yīng)用的運(yùn)行狀態(tài),比如,消耗了多少資源,發(fā)送了多少郵件和應(yīng)用運(yùn)行的日志等。
◆ 本地開發(fā)環(huán)境:主要是幫助用戶在本地開發(fā)和調(diào)試基于GAE的應(yīng)用,包括用于安全調(diào)試的沙盒,SDK和IDE插件等工具。
應(yīng)用服務(wù)器
應(yīng)用服務(wù)器依據(jù)其支持語言的不同而有不同的實(shí)現(xiàn)。
Python的實(shí)現(xiàn)
Python版應(yīng)用服務(wù)器的基礎(chǔ)就是普通的Python 2.5.2版的Runtime,并考慮在在未來版本中添加對(duì)Python 3的支持,但是因?yàn)镻ython 3對(duì)Python而言,就好比Java2之于Java1,跨度非常大,所以引入Python3的難度很大。在Web技術(shù)方面,支持諸如 Django,CherryPy,Pylons和Web2py等Python Web框架,并自帶名為"WSGI"的CGI框架。雖然Python版應(yīng)用服務(wù)器是基于標(biāo)準(zhǔn)的Python Runtime,但是為了安全并更好地適應(yīng)App Engine的整體架構(gòu),對(duì)運(yùn)行在應(yīng)用服務(wù)器內(nèi)的代碼設(shè)置了很多方面的限制,比如不能加載用C編寫Python模塊和無法創(chuàng)建Socket等。
Java的實(shí)現(xiàn)
在實(shí)現(xiàn)方面,Java版應(yīng)用服務(wù)器和Python版基本一致,也是基于標(biāo)準(zhǔn)的Java Web容器,而且選用了輕量級(jí)的Jetty技術(shù),并跑在Java 6上。通過這個(gè)Web容器不僅能運(yùn)行常見的Java Web 技術(shù),包括Servlet,JSP,JSTL和GWT等,而且還能跑大多數(shù)常用的Java API(App Engine有一個(gè)The JRE Class White List(http://code.google.com/intl/zh-CN/appengine/docs/java/jrewhitelist.html)來 定義那些Java API能在App Engine的環(huán)境中被使用)和一些基于JVM的腳本語言,例如JavaScript,Ruby或Scala等,但同樣無法創(chuàng)建Socket和 Thread,或者對(duì)文件進(jìn)行讀寫,也不支持一些比較高階的API和框架,包括JDBC,JSF,Struts 2,RMI,JAX-RPC和Hibernate等。
Datastore
Datastore提供了一整套強(qiáng)大的分布式數(shù)據(jù)存儲(chǔ)和查詢服務(wù),并能通過水平擴(kuò)展來支撐海量的數(shù)據(jù)。但Datastore并不是傳統(tǒng)的關(guān)系型數(shù)據(jù) 庫,它主要以"Entity"的形式存儲(chǔ)數(shù)據(jù),一個(gè)Entity包括一個(gè)Kind(在概念上和數(shù)據(jù)庫的Table比較類似)和一系列屬性。
Datastore提供強(qiáng)一致性和樂觀(optimistic)同步控制,而在事務(wù)方面,則支持本地事務(wù),也就是在只能同一個(gè)Entity Group內(nèi)執(zhí)行事務(wù)。
在接口方面,Python版提供了非常豐富的接口,而且還包括名為GQL的查詢語言,而Java版則提供了標(biāo)準(zhǔn)的JDO和JPA這兩套API。
而且Google已經(jīng)在今年的Google I/O大會(huì)上宣布將在未來的App Engine for Business套件中包含標(biāo)準(zhǔn)的SQL數(shù)據(jù)庫服務(wù),但現(xiàn)在還不確定這個(gè)SQL數(shù)據(jù)庫的實(shí)現(xiàn)方式,是基于開源的MySQL技術(shù),還是基于其私有的實(shí)現(xiàn),這是一個(gè)問題。
服務(wù)
Memcache
Memcache是大中型網(wǎng)站所備的服務(wù),主要用來在內(nèi)存中存儲(chǔ)常用的數(shù)據(jù),而App Engine也包含了這個(gè)服務(wù)。有趣的是App Engine的Memcache也是由Brad Fitzpatrick開發(fā)。
URL抓取(Fetch)
App Engine的應(yīng)用可以通過URL抓取這個(gè)服務(wù)抓取網(wǎng)上的資源,并可以這個(gè)服務(wù)來與其他主機(jī)進(jìn)行通信。這樣避免了應(yīng)用在Python和Java環(huán)境中無法使用Socket的尷尬。
App Engine應(yīng)用使用這個(gè)服務(wù)來利用Gmail的基礎(chǔ)設(shè)施來發(fā)送電子郵件。
計(jì)劃任務(wù)(Cron)
計(jì)劃服務(wù)允許應(yīng)用在指定時(shí)間或按指定間隔執(zhí)行其設(shè)定的任務(wù)。這些任務(wù)通常稱為Cron job。
圖形
App Engine 提供了使用專用圖像服務(wù)來操作圖像數(shù)據(jù)的功能。圖像服務(wù)可以調(diào)整圖像大小,旋轉(zhuǎn)、翻轉(zhuǎn)和裁剪圖像。它還能夠使用預(yù)先定義的算法提升圖片的質(zhì)量。
用戶認(rèn)證
App Engine的應(yīng)用可以依賴Google帳戶系統(tǒng)來驗(yàn)證用戶。App Engine還將支持OAuth。
XMPP
在App Engine上運(yùn)行的程序能利用XMPP服務(wù)和其他兼容XMPP的IM服務(wù)(比如Google Talk)進(jìn)行通信。
任務(wù)隊(duì)列(Task Queue)
App Engine應(yīng)用能通過在一個(gè)隊(duì)列插入任務(wù)(以Web Hook的形式)來實(shí)現(xiàn)后臺(tái)處理,而且App Engine會(huì)根據(jù)調(diào)度方面的設(shè)置來安排這個(gè)隊(duì)列里面的任務(wù)執(zhí)行。
Blobstore
因?yàn)镈atastore最多支持存儲(chǔ)1MB大小的數(shù)據(jù)對(duì)象,所以App Engine推出了Blobstore服務(wù)來存儲(chǔ)和調(diào)用那些大于1MB但小于2G的二進(jìn)制數(shù)據(jù)對(duì)象。
Mapper
Mapper可以認(rèn)為就是"Map Reduce"中的Map,也就是能通過Mapper API對(duì)大規(guī)模的數(shù)據(jù)進(jìn)行平行的處理,這些數(shù)據(jù)可以存儲(chǔ)在Datastore或者Blobstore,但這個(gè)功能還處于內(nèi)部開發(fā)階段。
Channel
其實(shí)Channel就是我們常說的"Comet",通過Channel API能讓應(yīng)用將內(nèi)容直接推至用戶的瀏覽器,而不需常見的輪詢。
除了Java版的Memcache,Email和URL抓取都是采用標(biāo)準(zhǔn)的API之外,其他服務(wù)無論是Java版還是Python版,其API都是私有的,但是提供了豐富和細(xì)致的文檔來幫助用戶使用。
管理界面
用了讓用戶更好地管理應(yīng)用,Google提供了一整套完善的管理界面,地址是http://appengine.google.com/ ,而且只需用戶的Google帳戶就能登錄和使用。下圖為其截屏:
圖1. 管理界面(點(diǎn)擊看大圖)
使用這個(gè)管理界面可執(zhí)行許多操作,包括創(chuàng)建新的應(yīng)用程序,為這個(gè)應(yīng)用設(shè)置域名,查看與訪問數(shù)據(jù)和錯(cuò)誤相關(guān)的日志,觀察主要資源的使用狀況。
本地開發(fā)環(huán)境
為了安全起見,本地開發(fā)環(huán)境采用了沙箱(Sandbox)模式,基本上和上面提到的應(yīng)用服務(wù)器的限制差不多,比如無法創(chuàng)建Socket和 Thread,也無法對(duì)文件進(jìn)行讀寫。Python版App Engine SDK是以普通的應(yīng)用程序的形式發(fā)布,本地需要安裝相應(yīng)的Python Runtime,通過命令行方式啟動(dòng)Python版的Sandbox,同時(shí)也可以在安裝有PyDev插件的Eclipse上啟動(dòng)。Java版App Engine SDK是以Eclispe Plugin形式發(fā)布,只要用戶在他的Eclipse上安裝這個(gè)Plugin,用戶就能啟動(dòng)本地Java沙箱來開發(fā)和調(diào)試應(yīng)用。
編程模型
因?yàn)锳pp Engine主要為了支撐Web應(yīng)用而存在,所以Web層編程模型對(duì)于App Engine也是最關(guān)鍵的。App Engine主要使用的Web模型是CGI,CGI全稱為"Common Gateway Interface",它的意思非常簡單,就是收到一個(gè)請(qǐng)求,起一個(gè)進(jìn)程或者線程來處理這個(gè)請(qǐng)求,當(dāng)處理結(jié)束后這個(gè)進(jìn)程或者線程自動(dòng)關(guān)閉,之后是不斷地重 復(fù)這個(gè)流程。由于CGI這種方式每次處理的時(shí)候,都要重新起一個(gè)新的進(jìn)程或者線程,可以說在資源消耗方面還是很厲害的,雖然有線程池(Thread Pool)這樣的優(yōu)化技術(shù)。但是由于CGI在架構(gòu)上的簡單性使其成為GAE***的編程模型,同時(shí)由于CGI支持無狀態(tài)模式,所以也在伸縮性方面非常有優(yōu) 勢(shì)。而且App Engine的兩個(gè)語言版本都自帶一個(gè)CGI框架:在Python平臺(tái)為WSGI。在Java平臺(tái)則為經(jīng)典的Servlet。最近,由于App Engine引入了計(jì)劃任務(wù)和任務(wù)隊(duì)列這兩個(gè)特性,所以App Engine已經(jīng)支持計(jì)劃任務(wù)和后臺(tái)進(jìn)程這兩種編程模型。
限制和資費(fèi)
首先,談一下App Engine的使用限制,具體請(qǐng)看下表:
類別 | 限制 |
Datastore中每個(gè)對(duì)象的大小 |
1MB |
每個(gè)開發(fā)者所擁有的項(xiàng)目 |
10個(gè) |
每個(gè)項(xiàng)目的文件數(shù) |
1000個(gè) |
每個(gè)項(xiàng)目代碼的大小 |
150MB |
每個(gè)請(qǐng)求最多執(zhí)行時(shí)間 |
30秒 |
Blobstore(二進(jìn)制存儲(chǔ))的大小 |
1GB |
HTTP Response的大小 |
10MB |
表1. App Engine的使用限制
雖然這些限制對(duì)開發(fā)者是一種障礙,但對(duì)App Engine這樣的多租戶環(huán)境而且卻是非常重要的,因?yàn)槿绻粋€(gè)租戶的應(yīng)用消耗過多的資源的話,將會(huì)影響到在臨近應(yīng)用的正常使用,而App Engine上面這些限制就是為了是運(yùn)行在其平臺(tái)上面應(yīng)用能安全地運(yùn)行著想,避免了一個(gè)吞噬資源或惡性的應(yīng)用影響到臨近應(yīng)用的情況。除了安全的方面考慮之 后,還有伸縮的原因,也就是說,當(dāng)一個(gè)應(yīng)用的所占空間(footprint)處于比較低的狀態(tài),比如少于1000個(gè)文件和大小低于150MB等,那么能夠 非常方便地通過復(fù)制應(yīng)用來實(shí)現(xiàn)伸縮。
接著,談一下資費(fèi)情況,App Engine的資費(fèi)情況主要有兩個(gè)特點(diǎn):其一是免費(fèi)額度高,現(xiàn)有免費(fèi)的額度能支撐一個(gè)中型網(wǎng)站的運(yùn)行,且不需付任何費(fèi)用。其二是資費(fèi)項(xiàng)目非常細(xì)粒度,普通 IaaS服務(wù)資費(fèi),主要就是CPU,內(nèi)存,硬盤和網(wǎng)絡(luò)帶寬這四項(xiàng),而App Engine則除了常見的CPU和網(wǎng)絡(luò)帶寬這兩項(xiàng)之外,還包括很多應(yīng)用級(jí)別的項(xiàng)目,比如:Datastore API和郵件API的調(diào)用次數(shù)等。具體資費(fèi)的機(jī)制是這樣的:如果用戶的應(yīng)用每天消費(fèi)的各種資源都低于這個(gè)額度,那們用戶無需支付任何費(fèi)用,但是當(dāng)免費(fèi)額度 被超過的時(shí)候,用戶就需要為超過的部分付費(fèi)。因?yàn)锳pp Engine整套資費(fèi)標(biāo)準(zhǔn)比較復(fù)雜,所以在這里就主要介紹一下它的免費(fèi)額度,具體請(qǐng)看下表:
類型 |
數(shù)量(每天) |
郵件API調(diào)用 |
7000次 |
傳出(outbound)帶寬 |
10G |
傳入(inbound)帶寬 |
10G |
CPU時(shí)間 |
46個(gè)小時(shí) |
HTTP請(qǐng)求 |
130萬次 |
Datastore API |
1000萬次 |
存儲(chǔ)的數(shù)據(jù) |
1G |
URL抓取的API |
657千次 |
表2. App Engine的免費(fèi)額度表
從上面免費(fèi)額度來看,除了存儲(chǔ)數(shù)據(jù)的容量外,其它都是非常強(qiáng)大的。
#p#
三、Google App Engine架構(gòu)
設(shè)計(jì)理念
App Engine在設(shè)計(jì)理念方面,主要可以總結(jié)為下面這五條:
◆ 重用現(xiàn)有的Google技術(shù):大家都知道,重用是軟件工程的核心理念之一,因?yàn)橥ㄟ^重用不僅能減低開發(fā)成本,而且能簡化架構(gòu)。在App Engine開發(fā)的過程中,重用的思想也得到了非常好的體現(xiàn),比如Datastore是基于Google的bigtable技術(shù),Images服務(wù)是基于 Picasa的,用戶認(rèn)證服務(wù)是利用Google Account的,Email服務(wù)是基于Gmail的等。
◆ 無狀態(tài):為了讓更好地支持?jǐn)U展,Google沒有在應(yīng)用服務(wù)器層存儲(chǔ)任何重要的狀態(tài),而主要在datastore這層對(duì)數(shù)據(jù)進(jìn)行持久化,這樣當(dāng)應(yīng)用流量突然爆發(fā)時(shí),可以通過為應(yīng)用添加新的服務(wù)器來實(shí)現(xiàn)擴(kuò)展。
◆ 硬限制:App Engine對(duì)運(yùn)行在其之上的應(yīng)用代碼設(shè)置了很多硬性限制,比如無法創(chuàng)建Socket和Thread等有限的系統(tǒng)資源,這樣能保證不讓一些惡性的應(yīng)用影響到與其臨近應(yīng)用的正常運(yùn)行,同時(shí)也能保證在應(yīng)用之間能做到一定的隔離。
◆ 利用Protocol Buffers技術(shù)來解決服務(wù)方面的異構(gòu)性:應(yīng)用服務(wù)器和很多服務(wù)相連,有可能會(huì)出現(xiàn)異構(gòu)性的問題,比如應(yīng)用服務(wù)器是用Java寫的,而部分服務(wù)是用 C++寫的等。Google在這方面的解決方法是基于語言中立,平臺(tái)中立和可擴(kuò)展的Protocol Buffer,并且在App Engine平臺(tái)上所有API的調(diào)用都需要在進(jìn)行RPC(Remote Procedure Call,遠(yuǎn)程方面調(diào)用)之前被編譯成Protocol Buffer的二進(jìn)制格式。
◆ 分布式數(shù)據(jù)庫:因?yàn)锳pp Engine將支撐海量的網(wǎng)絡(luò)應(yīng)用,所以獨(dú)立數(shù)據(jù)庫的設(shè)計(jì)肯定是不可取的,而且很有可能將面對(duì)起伏不定的流量,所以需要一個(gè)分布式的數(shù)據(jù)庫來支撐海量的數(shù)據(jù)和海量的查詢。
組成部分
圖1. GAE的架構(gòu)圖(圖源自參[6])
簡單而言,其架構(gòu)可以分為三個(gè)部分:前端,Datastore和服務(wù)群:
前端
共包括四個(gè)模塊:
◆ Front End:既可以認(rèn)為它是Load Balancer,也可以認(rèn)為它是Proxy,它主要負(fù)責(zé)負(fù)載均衡和將請(qǐng)求轉(zhuǎn)發(fā)給App Server(應(yīng)用服務(wù)器)或者Static Files等工作。
◆ Static Files:在概念上,比較類似于CDN(Content Delivery Network,內(nèi)容分發(fā)網(wǎng)絡(luò)),用于存儲(chǔ)和傳送那些應(yīng)用附帶的靜態(tài)文件,比如圖片,CSS和JS腳本等。
◆ App Server:用于處理用戶發(fā)來的請(qǐng)求,并根據(jù)請(qǐng)求的內(nèi)容來調(diào)用后面的Datastore和服務(wù)群。
◆ App Master:是在應(yīng)用服務(wù)器間調(diào)度應(yīng)用,并將調(diào)度之后的情況通知Front End。
Datastore
它是基于BigTable技術(shù)的分布式數(shù)據(jù)庫,雖然其也可以被理解成為一個(gè)服務(wù),但是由于其是整個(gè)App Engine唯一存儲(chǔ)持久化數(shù)據(jù)的地方,所以其是App Engine中一個(gè)非常核心的模塊。其具體細(xì)節(jié)將在下篇和大家討論。
服務(wù)群
整個(gè)服務(wù)群包括很多服務(wù)供App Server調(diào)用,比如Memcache,圖形,用戶,URL抓取和任務(wù)隊(duì)列等。
Python版和Java版App Engine在實(shí)現(xiàn)方面的區(qū)別
因?yàn)榇蠖鄶?shù)服務(wù)都可以被這兩個(gè)版本共享,所以兩者之間的區(qū)別主要集中在App Server端,Python版App Server應(yīng)該是經(jīng)過Google修改的Python Runtime,版本號(hào)應(yīng)該是2.5.2,而Java版App Server是基于Jetty 6的,因?yàn)樗捏w積和最常用的Tomcat相比更嬌小,這樣能使得一臺(tái)服務(wù)器支持更多的應(yīng)用,而且其應(yīng)該經(jīng)過Google的一定的修改。
流程
在這里舉一個(gè)普通的HTTP請(qǐng)求的處理流程為例:
◆ 用戶發(fā)送一個(gè)HTTP請(qǐng)求。
◆ Front End接受這個(gè)請(qǐng)求,并將這個(gè)請(qǐng)求轉(zhuǎn)發(fā)給一個(gè)空閑的App Server。
◆ App Server會(huì)處理這個(gè)請(qǐng)求。
◆ 檢查用于處理這個(gè)請(qǐng)求的Handler是不是已經(jīng)被初始化了,如果沒有的話,需要對(duì)這個(gè)Handler進(jìn)行初始化。
◆ 調(diào)用服務(wù)群的用戶認(rèn)證服務(wù)來對(duì)用戶進(jìn)行認(rèn)證,如果失敗的話,需要終止整個(gè)請(qǐng)求的處理工作,并返回用戶無法被認(rèn)證的信息。
◆ 查看這個(gè)請(qǐng)求所需的數(shù)據(jù)是否已經(jīng)緩存在Memcahe中,如果沒有的話,將對(duì)Datastore發(fā)出查詢請(qǐng)求來得到數(shù)據(jù)。
◆ 通過整合上步得到數(shù)據(jù)來生成相關(guān)的HTML,并返回給用戶。
◆ 由于HTML里面會(huì)包含對(duì)一些靜態(tài)文件的引用,比如圖片和CSS等,所以當(dāng)用戶收到HTML之后,還會(huì)通過Front End對(duì)Static Files里面存儲(chǔ)的靜態(tài)文件進(jìn)行讀取。
四、Database設(shè)計(jì)
使用方面
首先,在編程方面,Datastore是基于"Entity(實(shí)體)"這個(gè)概念,而且Entity和"對(duì)象"這個(gè)概念比較類似,同時(shí)Entity可 以包括多個(gè)Property(屬性),Property的類別有整數(shù),浮點(diǎn)和字符串等,比如,可以設(shè)計(jì)一個(gè)名為"Person"的Entity,它包含名 為"Name"的字符串Property和名為"Age"的整數(shù)Property。由于Datastore是"Schema-less"的,所以數(shù)據(jù)的 Schema都由應(yīng)用維護(hù),而且能非常方便地對(duì)一個(gè)Entity所包含的屬性進(jìn)行增刪和修改。在存儲(chǔ)方面,一個(gè)Entity的實(shí)例可以被認(rèn)為是一個(gè)普通 的"Row(行)",而包含所有這種Entity的實(shí)例的Table被稱為Kind,比如,所有通過"Person"這個(gè)Entity生成實(shí)例,比如小 吳,小朱和小華等,它們都會(huì)存放在同一個(gè)名為"Person"的Kind中。在結(jié)構(gòu)方面,雖然也能通過特定的方式在Datastore中實(shí)現(xiàn)關(guān)系型結(jié)構(gòu), 但是Datastore在設(shè)計(jì)上是為層次(Hierarchical)性結(jié)構(gòu)"度身定做"的,有Root Entity和Child Entity之分,比如,可以把"Person"作為Root Entity(父實(shí)體),"Address"作為"Person"的Child Entity,兩者合在一起可以稱為一個(gè)"Entity Group"。這樣做的好處是能將這兩個(gè)實(shí)體集中一個(gè)BigTable本地分區(qū)中,而且能對(duì)這兩個(gè)實(shí)體進(jìn)行本地事務(wù)。
接下來,將談一下Datastore支持那些高級(jí)功能:其一是提供名為GQL(Google Query Language)的查詢語言,GQL是SQL的一個(gè)非常小的子集,包括對(duì)">","<"和"="等操作符。其二是App Engine會(huì)根據(jù)代碼中查詢語句來自動(dòng)生成相應(yīng)Index,但不支持對(duì)Composite Index生成。其三是雖然由于Datastore分布式的設(shè)計(jì),所以在速度方面和傳統(tǒng)的關(guān)系型數(shù)據(jù)庫相比一定的差距,但是Google的架構(gòu)師保證大部 分對(duì)Datastore的操作能在200ms之內(nèi)完成,同時(shí)也得益于它的分布式設(shè)計(jì),使得它在擴(kuò)展性方面特別出色。其四是Datastore也支持在實(shí)體 之間創(chuàng)建關(guān)系,比如在Python版App Engine中可以使用ReferenceProperty在實(shí)體間構(gòu)建一對(duì)多和多對(duì)多的關(guān)系。
下表為Datastore和傳統(tǒng)的關(guān)系型數(shù)據(jù)庫之間的比較:
Datastore |
關(guān)系型數(shù)據(jù)庫 | |
SQL支持 | 只支持一些基本的查詢 |
全部支持 |
主要結(jié)構(gòu) | 層次(Hierarchical) |
關(guān)系 |
Index | 部分可自動(dòng)創(chuàng)建 |
手動(dòng)創(chuàng)建 |
事務(wù) | 只支持在一個(gè)Entity Group內(nèi)執(zhí)行 |
支持 |
平均執(zhí)行速度(ms) | 低于200 |
低于100 |
擴(kuò)展型 | 非常好 |
很困難,而且需要進(jìn)行大量的修改 |
表1. Datastore和關(guān)系型數(shù)據(jù)庫之間的比較
***,在接口方面,Python版提供一套私有的API和框架,在基本功能方面,比較容易學(xué)習(xí),但在部分高級(jí)功能方面,比如關(guān)系和事務(wù)等方面,學(xué)習(xí) 難度很高;Java版的API是基于JDO和JPA這兩套官方的ORM標(biāo)準(zhǔn),但是和現(xiàn)在事實(shí)的標(biāo)準(zhǔn)Hibernate有一定的差異。
實(shí)現(xiàn)方面
在實(shí)現(xiàn)方面,Datastore是在BigTable的基礎(chǔ)上構(gòu)建的,所以本段會(huì)首先重新介紹一下BigTable,之后會(huì)介紹Datastore的兩個(gè)組成部分:Entities Table和Index,***會(huì)講一下它在事務(wù)和備份這兩方面所采用的機(jī)制。
BigTable
在本系列的***篇已經(jīng)按照Google的Paper對(duì)BigTable技術(shù)做了一定的介紹,但其實(shí)BigTable本身其實(shí)沒有之前介紹的那樣復(fù) 雜,其實(shí)就是一個(gè)非常巨大的Table,這也是是它之所以名為"BigTable"的原因,而且結(jié)構(gòu)就像圖1那樣非常簡單,就是一個(gè)個(gè)ROW,每個(gè)ROW 都有一個(gè)Name和一組Cloumn,但是為了支持海量的數(shù)據(jù),它將這個(gè)大的Table進(jìn)行分片(Sharding)處理,每臺(tái)服務(wù)器存儲(chǔ)一個(gè)海量的 Table的一小部分,并且為了查詢效率,會(huì)對(duì)這個(gè)Table進(jìn)行排序。就像App Engine的創(chuàng)始人之一Ryan Barrett所說的那樣"BigTable is a sharded, sorted array "。
圖1. BigTable簡化版模型
在功能方面,首先,BigTable支持基本的CRUD操作,也就是增加(Create),查詢(Read),更新(Update)和刪除(Delete)。其次支持對(duì)Single-Row的事務(wù)與基于前綴和范圍的掃描。
Entities Table
它是Datastore最核心的Table,是以BigTable的形式存在的,主要用于存儲(chǔ)所有的Entity,而且是格式非常簡單,每行都會(huì)有 一個(gè)Row Name,也稱為Entity Key(可認(rèn)為它是一個(gè)Entity的Primary Key),而且只有唯一一個(gè)Column,主要用于存放被序列化的Entity。每個(gè)Entity的Key的生成是基于它的父Entity(如果有的話) 和其父至上的Entity,直到其Root Entity。以下圖為例,timmy的父Entity是jane,jane的父Entity兼Root Entity是Ethel,所以***timmy的Entity Key是"/Grandparent:Ethel/Parent:Jane/Child:Timmy"。
圖2. Entity Key的例子
Index
Index主要是為方便和加速查詢而生的,所以在切入Index之前,先介紹一下Datastore主要支持那些查詢,主要有三類:其一是基于Kind的,其二是基于Property值的,其三是基于多個(gè)Property值的。
Index表也是以BigTable的形式存在,但是和上面的Entities Table是分離的,主要用來單獨(dú)存放那些需要被Index的數(shù)據(jù),而且由于怕Index表體積太大,所以不會(huì)有時(shí)將其放置在內(nèi)存中以提升查詢速度。
主要有下面這幾種Index表:
◆ Kind Index:用于加速那些用于獲取所有屬于某個(gè)Kind的Entity的查詢,比如把所有屬于Person這個(gè)Kind的Entity,包括小吳,小朱和 小華等提取出來,Kind Index表每行有Kind和Entity Key這兩個(gè)列,此Index會(huì)有系統(tǒng)自動(dòng)生成。
◆ Single-property Index:用于加速那些基于單一屬性值的查詢,比如要找出所有Age在20之下的Person,Age就是所謂的那個(gè)單一屬性值,Single- property Index表每行除了Kind和Entity Key之外,還有屬性名和屬性值這兩個(gè)列,此Index也會(huì)有系統(tǒng)自動(dòng)生成,還會(huì)根據(jù)升降序的不同,生成兩個(gè)表。
◆ Composite Index:用于加速那些基于對(duì)多個(gè)屬性值的查詢,Composite Index表基本和上面的Single-property Index表非常類似,但是每行包括多個(gè)屬性名和屬性值,而且由于此Index消耗資源非常多,所有由開發(fā)人自己確定是不是需要這個(gè)Index,系統(tǒng)不自 動(dòng)生成。
事務(wù)
原則上所有對(duì)單一Entity的Write操作都是事務(wù)的,并基于上面提到的BigTable的Single-Row事務(wù)和Optimistic Concurrency Control這兩個(gè)技術(shù),下面是流程:首先,系統(tǒng)會(huì)讀這個(gè)Entity的Committed Timestamp(提交時(shí)間戳),Write會(huì)以串行(Serialized)的形式寫入到BigTable的日志中,之后,系統(tǒng)會(huì)將日志更新到 BigTable的表中,如果成功的話,系統(tǒng)會(huì)更新這個(gè)Entity的Committed Timestamp,但如果系統(tǒng)發(fā)現(xiàn)在更新之前,Committed Timestamp發(fā)生了變化,也就是說另一個(gè)事務(wù)在這個(gè)事務(wù)執(zhí)行過程中已經(jīng)對(duì)這個(gè)Entity進(jìn)行了操作,在這個(gè)時(shí)候,系統(tǒng)會(huì)重新執(zhí)行這個(gè)事務(wù)。由于在 整個(gè)事務(wù)過程采用Optimistic Concurrency Control,而不是Locking,所以在吞吐量方面表現(xiàn)不錯(cuò)。
如果要對(duì)多個(gè)Entity執(zhí)行事務(wù),那就需要將這幾個(gè)Entity設(shè)為一個(gè)Entity Group,也就意味著將這幾個(gè)Entity放在同一臺(tái)物理機(jī)上。在執(zhí)行的時(shí)候,會(huì)將以Root Entity的Committed Timestamp為準(zhǔn)來對(duì)所有參與事務(wù)的Entity進(jìn)行和上面差不多的事務(wù)操作。
備份
與BigTable基于Row級(jí)別的備份不同的是,Datastore是基于Enity Group級(jí)別,而且采用Paxos算法,所以Datastore的備份方法比BigTable的更安全。
總體而言,Datastore在設(shè)計(jì)理念上和傳統(tǒng)的關(guān)系型數(shù)據(jù)庫有很大的不同,所以其在反應(yīng)速度和寫數(shù)據(jù)方面不是***的,但是現(xiàn)在Web應(yīng)用以讀為 主,而且需要能通過簡單的擴(kuò)展就能支持其海量的數(shù)據(jù),而這兩點(diǎn)卻是Datastore所擅長,所以Datastore非常適合支撐Web應(yīng)用。
對(duì)于Googe App Engine架構(gòu)的介紹就到這里了,另外其實(shí)還有很多網(wǎng)站的架構(gòu)也是比較經(jīng)典的,像我以前介紹過的Facebook架構(gòu)、MySpace架構(gòu)、優(yōu)酷架構(gòu)、Twitter架構(gòu)、Flickr架構(gòu)等等,有興趣的朋友可以關(guān)注一下這方面的技術(shù)資料,因?yàn)椤霸啤鄙蟻砹耍@些都是我們學(xué)習(xí)的基礎(chǔ)。
***感謝作者吳朱華,膜拜一下....
原文:http://peopleyun.com/
【編輯推薦】