從零到 Go:Google感恩節火雞塗鴉開發紀實

發表於2011-12-16

來源:谷奧

本文是 Google 搜尋團隊軟體工程師 Reinaldo Aguiar 發表在 Go 語言部落格的客座文章,他分享了在一天之內完成首款 Go 程式的開發併發布給數百萬受眾的經歷。

我最近有幸參與了一項雖小卻曝光率極高的“20% 專案”——2011 年感恩節的 Google Doodle。這幅 doodle 中的火雞由不同樣式的頭、翅膀、羽毛與爪子隨機組合而成。使用者可以通過點選火雞的不同部位自定義組合。這種互動通過 JavaScript、CSS 實現,由瀏覽器實時渲染出各種火雞。

使用者製作出的個性化火雞可以分享到 Google+ 上。點選“分享”按鈕(圖中未給出)即可在使用者的 Google+ 流中生成一篇含有火雞圖片的帖子。要滿足這種需求,圖片必須是單獨一張,且與使用者所製作的火雞完全相同。

由於火雞的八個部位(頭、雙爪、幾片羽毛等)各有 13 種樣式,使用者可能設計出八億多種火雞。預先製作好八億多張圖片顯然行不通。因此,必須在服務端實時生成圖片。出於即時擴充套件性與高度可用性的共同需求,合適的平臺非常明顯:Google App Engine!

從零到 Go:24 小時內登上 Google 主頁的 Go 語言應用“火雞”doodle 開發紀實

接下來要決定的就是選用哪款 App Engine runtime 了。影象處理任務極度依賴 CPU,所以這種情況下效能是決定性因素。

為確保可靠,我們首先進行了測試。我們為新版 Python 2.7 runtime(該版本提供基於 C 的影象處理庫 PIL) 與 Go runtime 準備了一些等效的演示應用。各應用 分別合成幾張小圖片生成影象檔案,編碼為 JPEG,並將 JPEG 資料作為 HTTP 響應發回客戶端。Python 2.7 應用處理請求的中位響應時間為 65 毫秒,而 Go 應用的中位延時僅為 32 毫秒。

因此這成為了試用 Go runtime 的大好機會。

此前我對 Go 語言毫無經驗,而時間又很緊:兩天內達到生產需求。雖然緊張,我還是將它視作從另一常被忽略的方面——開發速度——測試 Go 的機會。完全沒有 Go 語言開發經驗的人能在多快的時間內掌握並開發出高效能高擴充套件性的應用?

設計

基本步驟是在 URL 中編碼火雞各態、實時繪製並編碼影象。

各 doodle 的基礎是背景圖畫:

從零到 Go:24 小時內登上 Google 主頁的 Go 語言應用“火雞”doodle 開發紀實

有效的請求 URL 形如:http://google-turkey.appspot.com/thumb/20332620

/thumb/ 後面跟著的數字字串(十六進位制)代表各外觀元素要繪製的形狀,如下圖所示:

從零到 Go:24 小時內登上 Google 主頁的 Go 語言應用“火雞”doodle 開發紀實

程式的請求接管器解析 URL 決定各元件所選定的元素,在背景上繪製對應影象,並返回 JPEG 成品。

如果出錯則返回預設影象。不必返回錯誤頁面,因為使用者不可能看到——瀏覽器肯定是在載入 image 標記中的 URL。

實現

在軟體包層面,我們宣告瞭一些資料結構,描述火雞的各個元素、對應影象所在資料夾,以及各影象應繪製在背景圖上的位置。

上述各點的幾何位置是通過影象中各元素的實際位置而得到的。

每次請求都從磁碟載入影象是很浪費的重複行為,因此我們在收到首個請求時就將全部 106 幅影象(13×8 個元素 + 1 幅背景 + 1 幅預設圖)載入到全域性變數中。

請求按下述順序處理:
1、解析請求 URL,按順序解碼出各字元的十進位制值。

2、為背景影象建立副本,作為最終影象的基礎。

3、在背景影象上繪製各影象元素(使用 layoutMap 判斷應繪製的位置。)

4、將影象編碼為 JPEG

5、將 JPEG 直接寫入 HTTP 響應寫入器中,將影象返回給使用者。

如果出錯,則將 defaultImage 返回給使用者,並在 App Engine 控制檯記下日誌,供日後分析之用。

下面是含說明註釋的請求接管器程式碼:

 

為簡潔起見,這些程式碼段中我省略了一些輔助函式。完整程式碼請參閱原始碼

效能

從零到 Go:24 小時內登上 Google 主頁的 Go 語言應用“火雞”doodle 開發紀實

該圖表從 App Engine 控制檯擷取,展示了釋出後的平均請求時間。顯然,即使在高負載情況下也沒有超過 60 ms,中位延遲時間為 32 ms。考慮請求接管器在處理影象並實時編碼,這已經相當快了。

結論

我覺得 Go 語言的語法直觀、簡單且潔淨。我過去常與解析型語言打交道,儘管 Go 是靜態錄入編譯型語言,編寫這款應用的感覺卻更像是在用動態解析型語言。

開發伺服器提供了可以在程式有變動後迅速重新編譯的 SDK,所以開發部署與解析型語言一樣快。而且非常簡單——我只花了不到一分鐘就配置好了開發環境。

Go 語言優秀的文件也幫助了我迅速完成開發。文件是從原始碼生成的,各函式的文件與相關聯的原始碼直接連結。這不僅可以讓開發者迅速理解特定函式的作用,還鼓勵開發者深入挖掘軟體包的實現,簡化了對良好程式設計風格與規則的掌握。

編寫這款應用的過程中,我只參考了三份資源:App Engine 的 Hello World Go 示例Go 軟體包文件以及一篇演示 Draw 軟體包的博文。感謝開發伺服器的迅速部署,以及該語言自身的優異特性,我得以在 24 小時內掌握該語言,並開發出超快、滿足生產需求的 doodle 生成器。

應用的完整原始碼(包括影象檔案)可以在 Google Code 專案中下載到。

向設計該 doodle 的 Guillermo Real 與 Ryan Germick 致以特別的謝意。

原文:From zero to Go: launching on the Google homepage in 24 hours

相關文章