《Serverless架構:無服務器單頁應用開發》講授如何利用AWSLambda創建Serverless單頁應用。這里,Serverless的意思是應用開發者無須管理服務器,將應用構建在服務之上,而不是運行在需要人工配置和維護的服務器之上。這種新的開發方式帶來很多好處,比如節省成本,可擴展性與可靠性高,以及開發者可以專注于實現應用的業務邏輯等。全書共8章,BenRady帶領讀者采用這種新方法從零開始開發一個JavaScript解題應用,并且對其進行測試,最終完成部署。
對于創業者以及中小企業的開發者來說,《Serverless架構:無服務器單頁應用開發》講述的Serverless設計是一個值得了解和學習的新方法,可以從中獲得啟示,抓住先機。
Serverless的意思就是開發應用時可以專注于實現應用的業務邏輯,不需要考慮管理服務器的事情。
采用無服務器架構的方式開發應用,擴展性好、可靠性強、成本低。
嘗試新創意、探索可能的新市場或者創建小可行產品的應用開發方式。
創業者、中小型公司的福音。數小時內就能搭建一個初始版本應用并在幾秒內部署,迅速接受市場檢驗。
我做了幾年單頁Web應用,一直希望能擺脫應用服務器施加的限制,現在愿望終于實現了。Amazon(還會有更多的其他公司)開發出的技術讓無服務器架構(serverless,在本書中簡稱為“無服”)成為可能,消除了很多構建和擴展Web應用的風險和成本。這個創意是如此令人嘆服,如此具有變革意義,以至于我必須為它寫一本書。
這本書是為那些希望在Web上構建一些東西的人而寫的。有的人想搭建一個應用——一個他們認為將會是下一個驚世之作的東西。有的人只是剛著手Web開發,從未構建過任何類型的應用——不管是影響世界的還是其他什么樣的。有的人則是已經用Java、RubyonRails或者Node.js構建過許多基于Model-View-Controller應用的資深Web開發者。隨著這個無服技術的興起,我希望能分享所學的一切,真心希望有人能夠用它做出一些了不起的東西。
在前言中,你將了解本書的主題以及能用這些技術來實現些什么。
指導原則
寫這本書時我腦子里有幾條指導原則。這些原則的目的是讓本書內容具有針對性、易理解,不說廢話。這里把它們列出來,幫助你了解我是如何寫這本書的以及更好地理解本書的相關背景。
有些原則可能是有爭議的,其中一些甚至與構建Web應用的主流思想相左。但是,這些原則將幫助你深入理解這個主題。與其波瀾不驚,存在爭議會更好。
使用Web標準和熟悉的工具
在這本書中,你將使用一小部分精選的工具來構建一個單頁Web應用。在本書的某些節點上,你將會實現其他工具已有的功能,這些工具是我有意不在應用中引入的。你可能會好奇,既然它們提供了所需的功能,為什么我們不用呢?
閱讀本書實際上是一個學習的過程。當學習知識時,使用熟悉的工具是有幫助的。不然,花在學習工具上的時間比花在學習技術上的還要多。我不希望對一個框架或者庫的選擇讓我們偏離本書主題。這本書是關于無服Web應用,而不是關于框架或者類庫的。為了保持未知性,我們將會使用那些Web開發者熟悉的工具(例如jQuery)、Web標準和Web服務,來實現一個無服設計。
有可能讀完這本書,你將會接觸到一種客戶端Web框架,比如React或者Angular,來構建你自己的Web應用。這些工具近些年在Web開發者社區獲得了很多關注,我希望能看到很多使用它們的成功項目。在本書中學到的所有知識與你希望使用這些框架做的事情都是兼容的。它們是互為補充而不是相互沖突的關系。
使用函數式JavaScript
本書中你將不會創建JavaScript的任何類。創建類結構來解決問題對于一些具有富類型和面向對象類型系統的語言是合理的,但JavaScript不是這樣的語言。相反,我們將使用更易于理解的函數式風格。
這意味著你將不會遭遇this關鍵字的范圍問題。你將會避免原型和繼承的共同使用。
你不會使用new關鍵字和專門設計的函數來創建對象;相反,你將會使用一個字面意義的對象來創建它們:{}。
你可以自己決定這是否就是你希望采納的風格。因為這種方式擁有一些實際、立竿見影的好處,最后許多軟件設計決策實際上都會偏向這種風格。代碼終究應該首先是給人寫的,然后才是計算機。只要它可執行,對于計算機而言代碼看起來如何無所謂。
避免無用功
做項目時,我的目標一直都是:持續交付有改進的結果,只要這個改進是朝著環境需要的方向在進行。實現這個目標意味著要避免任何能造成交付率被消磨的事情,比如剃牦牛(yakshaving)。
如果你對“剃牦牛”這個詞不熟悉的話,想象一下你想要給朋友買一件毛衣。你走進一家商店卻發現沒有毛衣賣。幸運的是,那里的另一位客戶知道街角有一個很好的裁縫,他可能可以為你做一件。所以你到了裁縫那兒,他有一個非常好看的毛衣圖案和一臺能編織這個圖案的機器,但毛線供應商今天還沒送貨。所以你跑到供應商那兒……
然后這個過程一直繼續,直到你發現自己在西藏的一片牧場上剃耗牛毛來編毛線。“我怎么來這里了?”你可能會問自己,“我所需要的只是一件毛衣。”當一系列看起來相關和必要的任務讓你從真實目標上偏離時,你就是在剃耗牛。幸運的是,剃耗牛的解決辦法很簡單,就是意識到你自己一直在剃耗牛,然后轉而買一頂帽子。
我希望你在閱讀本書時不要剃耗牛。這就是為什么我用了一個預備好的工作空間以及盡可能少的工具的原因。你應該把時間花在學習上,而不是安裝軟件、配置和排錯上。
通過測試來加快進度
你有沒有曾經害怕過修改甚至只是修改一點點代碼?也許你當時不確定應該做什么或者為什么應該做這個。“首先,不作惡”對程序員和醫生而言均適用。這種情況會讓你感覺進退兩難。
設想你做這些改動時,有一位可信的同事——這類系統的專家——就坐在你身邊。如果你引入任何缺陷到系統中,他就會攔住你,清楚而明確地告訴你為什么這個改動是個壞主意。如果你有這樣可信的同事,是否還會進退兩難?
不確定性拖慢了我們的腳本,并且限制了解決方案的范圍。為了快速搭建一個軟件,你必須有自信。為了獲得這份自信,你可以為自己創造一個自動化專家——它了解系統的所有細節,知道系統如何運轉以及為什么這樣運轉。這位專家和系統相輔相成,隨著它的改變而改變,互相影響。這個專家就是你編寫一套測試,它們快到能持續運行,每秒能運行成百上千的測試,而且每次在你對代碼進行修改之后都是如此。
一旦你有了測試套件,就擁有了新選擇。而當你不再害怕修改代碼時,就可以按照自己的設想來設計應用,而不是試圖讓它在一開始就要“正確”。這意味著你可以隨著形勢的變化快速適應這個世界,而不是試圖預測你可能需要和不需要什么。你可以基于當下的信息而不是靠猜來做決策,應用就會自然而然地變成它應該的那個樣子。
在本書中,你將使用測試驅動開發(TDD)技術來編寫應用和它的測試。了解如何用測試來構建軟件是一項技能,要獲得它的益處,就必須真正地使用它。我在本書中引入TDD的目的不僅是向你展示如何測試Web應用的特定功能,還想證明用它來測試典型Web應用有多簡單,如果你知道如何實現的話。
在實踐TDD的過程中,有一個三步循環,經常描述為紅—綠—重構。首先寫一個測試,檢查應用尚不具備的功能。如果測試如你預期的那樣失敗了,就可以相信它是在測試你希望加到應用上的功能。現在這些測試是紅色的。一旦有一個失敗的測試,添加幾條最簡單的代碼來讓這個測試通過,通常幾行代碼即可。現在這些測試是綠色的。
通過測試為應用添加一些功能后,就該后退一步,讓自己看得更全面一些。是否在實現中引入了一些重復代碼?所有的變量和函數是否都有描述性的準確名字?是否還有更簡單的方式?考慮這些事情,然后開始重構。重構是在不改變功能的情況下修改代碼。你之前編寫的測試會告訴你是否改變了功能,所以只能在這些測試都通過時重構,這一點很重要。有了它們作為你的安全防護網,可以在開始下一步測試之前清理完所有代碼的問題。
TDD用得越多,你的進展就會越快,從中獲得的價值就越多。通過一遍又一遍地重復“紅—綠—重構”過程,你將學會如何漸進式地構建一個設計合理、測試充分的應用。這樣你不僅對自己的應用有信心,而且對它進行持續的修改也更容易。
邊做邊學
本書是一本教程,所以你可以跟著書中的引導邊做邊學。通過這本書,你將構建一個無服單頁Web應用。本書的目的是用具體的方式解釋無服架構的原理。本書的成果是一個可運行的應用,所以你大可以放心,書中的技術就像廣告中說的那樣有用。
采用這種方式意味著篇幅有限,我對有些知識點不可能講得很深入。因此,我在每章中安排了一節“下一步”來提供一些主題,如果你希望了解更多,可以查找相關的資料。
從預備好的工作空間開始
為了讓你能快速上手,我提供了一個預備好的工作空間(preparedworkspace),里面包括了起步需要的所有東西,并且不需要太多時間來設置。這就好比你在畫一幅藝術品,我已經為你準備好顏料、畫架和畫布。你要做的就是創作。
為了能使用這個預備好的工作空間,你需要一臺兼容Bashshell的計算機來使用工作空間里面的腳本和工具。可以是OSX、任何*nix版本或者FreeBSD。如果你安裝了Cygwin,用Windows可能也行。你還需要一個帶開發者控制臺的Web瀏覽器。本書的大部分例子中使用的是GoogleChrome,但大多數情況下Firefox也能提供了類似的功能。
如何閱讀本書
閱讀一本書可以有很多種方式,不僅是從頭到尾的那種。至于如何閱讀本書,取決于你想要獲得什么。下面列出的是讀本書的一些常見理由,以及我對于如何使用這本書來實現這些目標的建議。
目標1:理解無服和傳統單頁應用的優劣
需要做什么
1.閱讀第1章的前3節理解兩種方式的優劣。
2.略讀第1章剩下的部分和第2~3章。
3.通讀第4~8章,盡可能跟著教程實現應用。
如果你是一個有經驗的Web開發者,搭建過單頁Web應用,希望了解更多有關無服Web應用的知識,你可能不需要看前3章的所有內容。這些章節展示了搭建單頁Web應用的vanilla.js方式。其意圖是闡述一個單頁Web應用的基礎模塊。我盡量定義哪些部分是必需的,并提供一些可供參考的基礎實現。如果你沒有給Web應用編寫過很多測試,可以在第2章中實現一些測試例子來學習一些新技能。
讀完第1章的前3節,你會希望集中精力細讀第4~8章。我建議你搭建一個簡單Web應用,或者至少一個原型,這樣你可以在后面的章節中自己嘗試這些技術。通過實驗可以學到很多。
目標2:搭建你的第一個單頁應用
需要做什么
1.在開始前,先讀一讀書中列出的必要的輔助閱讀材料。
2.從頭到尾讀完本書所有的章節,如果有必要,附錄也要看。
如果你是第一次搭建Web應用,你會希望閱讀整本書,從頭到尾讀一遍。另外,你可能也想跟上基礎Web技術的腳步,包含HTML、CSS和JavaScript,可以查閱下面的免費資源。等理解了這些主題,再來深入讀本書。
目標3:使用你喜歡的Web框架搭建一個無服應用
需要做什么
1.通讀第1章。
2.用你喜歡的Web框架實現第2章和第3章的測試與功能。
3.通讀第4~8章。
正如前面說的那樣,我不希望把這本書的重點放在Web框架上,但還是可以使用它們來搭建無服單頁應用。如果你對單頁應用的基本元素很熟悉,并且靠客戶端Web框架來提供這些功能,可以用喜歡的框架輕松重建我們在第2章和第3章實現的功能。一旦有了這個作為基礎,應該可以遵照本書余下的部分,用這個框架實現整個應用。
目標4:創建一個最小可行產品(MinimumViableProduct,MVP)
需要做什么
1.閱讀第1章的前3節,理解無服開發與傳統開發方式的優劣。
2.閱讀第8章來了解用這種方式構建一個MVP的成本。
3.如果這個方式看起來行得通,閱讀剩余的所有章節(如果有需要的話,包括附錄)。
3.使用預備好的工作空間作為搭建MVP的起點。
當啟動一個新產品或者一項新業務時,首要的挑戰是搞清楚市場想要什么以及它愿意為什么付錢。許多人稱之為產品/市場匹配(product/marketfit),這是構建一個成功產品或者服務的關鍵。
找到產品/市場匹配的一個有效方式是先做出一個產品并試著銷售。驗證市場的需求和你通過銷售或市場渠道連接這些客戶的能力,這是你應該盡快跨過的關鍵門坎。當然,你可能又沒那么多時間和資金來搭建一個完整的應用,所以一個替代方案是搭建一個MVP來驗證產品的核心價值。
無服單頁應用是嘗試新主意、探索可能的新市場或者創建MVP的好方式。搭建這類應用來替代傳統Web應用或者原生應用,意味著你可以更快接觸到客戶。你可以在若干小時內搭建一個初始版本并在幾秒內部署。這些應用可以立即更新,輕松地被拆分測試,可以提供詳細的使用指標,幫助你理解客戶想要的是什么。
除了運行起來不貴、快速構建以及幾乎所有用戶都能訪問之外,無服單頁應用可以“無限”(正如Amazon宣傳的那樣)擴展,這樣如果你的產品在市場上有旺盛的需求,你就可以滿足這樣的需求以及留住用戶。
在線資源
你可以在ProgmaticBookshelf官網找到這本書中的應用以及代碼。你還能在上面看到社區論壇和提交勘誤的表單,報告問題或者為未來的版本提供建議。
你可以在我的Github.com賬號(benrady)5下找到預備好的工作空間。如果你還沒有Github賬號,那就新建一個,并且fork我的代碼庫。想知道更多操作細節,可以閱讀第1章的內容。
BenRady
benrady@gmail.com
第1 章 從簡單開始 1
無服Web 應用 2
-- 無服設計的好處 4
-- 無服設計的限制 6
使用自己的工作空間 8
-- 本地執行 12
-- 創建著陸頁 13
部署到Amazon S3 15
-- 搭建AWS 命令行接口 16
-- 創建一個帶訪問密鑰的AWS 用戶 17
首次部署 20
-- 下一步 21
第2 章 基于hash 事件的視圖路由 23
設計可測試的路由器 24
-- 運行Jasmine 測試 25
-- 編寫第一個測試用例 26
路由函數 29
-- 創建命名空間 29
-- 添加路由函數 30
-- 創建視圖容器 32
添加路由 34
添加視圖參數 37
-- 用spy 測試調用 37
-- 處理視圖函數中的參數 39
-- 加載應用 41
-- 響應事件 42
-- 響應hash 事件 44
再次部署 46
-- 下一步 46
第3 章 單頁應用的必要組件 49
創建視圖 50
定義數據模型 53
-- 數據綁定 55
-- 優化數據模型 58
處理用戶輸入 60
-- 有效地使用視覺反饋 64
-- 控制導航 66
創建一個應用外殼 68
-- 提取著陸頁 68
-- 添加工具條 69
使用自定義事件 72
再次部署 75
-- 下一步 75
第4 章 基于Amazon Cognito 的認證服務 77
接入外部身份認證服務商 78
創建身份池 82
-- 身份池配置 83
-- IAM 角色和策略 84
獲取Google 身份. 87
請求AWS 證書 90
-- 刷新令牌 91
-- 基于Deferred 對象和Promise 的認證請求 93
-- 創建一個身份Deferred 對象 95
創建個人主頁視圖 96
再次部署 98
-- 下一步 99
第5 章 使用DynamoDB 存儲數據 101
使用DynamoDB 102
-- 理解DynamoDB 的鍵和哈希 102
-- DynamoDB 用作文檔數據庫 103
-- 強一致性和最終一致性 105
創建表 106
-- 屬性和鍵值 108
-- 預設吞吐量 109
-- 二級索引與查詢 vs 掃描 110
授權訪問DynamoDB 111
保存文檔 113
-- 一個fail-safe 的數據訪問函數 114
-- 創建和保存一個item 115
讀取文檔 117
數據訪問和驗證 119
重新部署 122
-- 下一步 122
第6 章 使用Lambda 構建微服務 125
理解Amazon Lambda 126
-- Lambda 環境 126
-- Lambda 的局限 128
-- 內存、時間和費用 129
先部署 130
-- 配置一個Lambda 函數 131
-- 創建代碼包 133
-- 通過AWS 控制臺測試函數 134
-- 創建一個新的Lambda 配置 135
-- 往Lambda 執行角色上添加策略 136
編寫Lambda 函數 138
-- 規避微服務架構問題 138
-- 添加服務依賴 140
-- 構建可測試的服務 141
-- 查詢、分組和分頁 143
調用Lambda 函數 145
使用Amazon API 網關 146
重新部署 148
-- 下一步 148
第7 章 無服應用的安全 151
保護你的AWS 賬號 152
-- 禁用所有root 訪問密鑰 152
-- 管理用戶配置 152
-- 保護AWS 證書 153
-- 設置多重身份認證 154
查詢注入攻擊 154
跨站腳本攻擊 156
-- XSS 注入方法 156
-- 使用web worker 沙盒化JavaScript 157
跨站請求偽造 159
-- 不用Javascript 實現XSRF 160
-- 跨站請求和同源策略 161
線路攻擊和傳輸層安全 162
-- Sidejacking 攻擊 162
-- 高效使用HTTPS 163
拒絕服務攻擊 165
-- 用CloudFront 保護S3 165
-- 可擴展服務和用戶身份 166
重新部署 167
-- 下一步 167
第8 章 擴容 169
監控Web 服務 169
-- 監控容量限制 170
-- 創建付款警告 173
分析S3 的流量 174
-- 記錄S3 請求 174
-- 分析S3 日志 177
-- 響應代碼頻率 179
-- 熱門資源 180
-- 每日用量 181
優化應用,實現增長 182
-- 通過緩存降低成本和加載時間 183
-- 通過帶版本號的文件名清除緩存 186
云的成本 187
-- 加載成本 188
-- 數據成本 188
-- 微服務成本 189
-- 加起來 190
再次部署 192
-- 下一步 192
附錄A 安裝Node.js 195
安裝Node.js 運行時 195
-- Linux 195
-- OS X 196
-- Windows 196
管理多個Node.js 版本 197
附錄B 分配一個域名 199
參考書目 201