Node.js是一個(gè)基于Chrome V8引擎的JavaScript運(yùn)行時(shí)環(huán)境,使用了高效、輕量級(jí)的事件驅(qū)動(dòng)、非阻塞 I/O 模型,讓JavaScript 運(yùn)行在服務(wù)端的開(kāi)發(fā)平臺(tái)。本書(shū)主要介紹基于Node.js構(gòu)建企業(yè)級(jí)后端服務(wù),內(nèi)容涉及Node.js和JavaScript的特性介紹、通信協(xié)議、擴(kuò)展、可觀測(cè)性、Docker容器、部署、容器編排、應(yīng)用程序容錯(cuò)、分布式單元、應(yīng)用程序安全性等內(nèi)容。本書(shū)不是面向 Node.js新手的,適用于擁有Node.js 實(shí)戰(zhàn)經(jīng)驗(yàn)且熟練掌握J(rèn)avaScript的開(kāi)發(fā)人員。讀完本書(shū),你會(huì)了解在生產(chǎn)環(huán)境中運(yùn)行 Node.js 服務(wù)所需的許多技術(shù)。
適讀人群 :擁有了Node.js的實(shí)戰(zhàn)經(jīng)驗(yàn)且能熟練使用JavaScript 從初創(chuàng)公司到世界500強(qiáng),大多數(shù)公司都喜歡使用Node.js來(lái)構(gòu)建高性能的后端服務(wù)。工程師對(duì)Node.js有很高的評(píng)價(jià),因?yàn)樗腥菀桌斫獾腁PI和大家熟悉的語(yǔ)法。在全球大的包存儲(chǔ)庫(kù)的強(qiáng)力支持下,Node.js的生態(tài)必將更加繁榮。
在本書(shū)中,作者證明了Node.js在構(gòu)建可觀察、可擴(kuò)展且有彈性的服務(wù)方面與傳統(tǒng)的企業(yè)平臺(tái)一樣適用。中高級(jí)Node.js開(kāi)發(fā)人員會(huì)發(fā)現(xiàn),他們可以將應(yīng)用程序代碼和現(xiàn)代服務(wù)的各個(gè)層面結(jié)合起來(lái)。
【通過(guò)學(xué)習(xí)本書(shū),你可以:】
了解為什么要運(yùn)行多個(gè)相同的Node.js服務(wù)副本。
根據(jù)業(yè)務(wù)場(chǎng)景選擇恰當(dāng)?shù)膮f(xié)議。
調(diào)整應(yīng)用程序容器以便在生產(chǎn)環(huán)境中運(yùn)行。
跟蹤分布式系統(tǒng)中的錯(cuò)誤,以確定哪個(gè)服務(wù)出錯(cuò)。
通過(guò)將工作轉(zhuǎn)移給反向代理來(lái)簡(jiǎn)化應(yīng)用程序代碼并提高性能。
構(gòu)建數(shù)據(jù)面板來(lái)監(jiān)視服務(wù)運(yùn)行狀況和數(shù)據(jù)吞吐量。
了解在企業(yè)環(huán)境中操作時(shí)需要使用多種工具的原因。
在舊金山的 NodeSchool 和 Ann Arbor 的 PHP MySQL 工作組工作的這幾年間,我一直致力于教授別人編程。到目前為止,我已經(jīng)教授過(guò)數(shù)百名學(xué)生。教學(xué)通常都是從安裝和配置所需的軟件開(kāi)始。接下來(lái),我會(huì)用一小段代碼和大段的語(yǔ)言向?qū)W生們解釋程序的運(yùn)行原理,學(xué)生們只需“點(diǎn)擊”即可。當(dāng)代碼運(yùn)行起來(lái)時(shí),學(xué)生們總是特別開(kāi)心,就像在游戲里習(xí)得了新技能一樣。
我的目標(biāo)就是讓讀者通過(guò)本書(shū)重現(xiàn)那種激動(dòng)人心的感覺(jué)。在本書(shū)中,你將發(fā)現(xiàn)許多實(shí)際操作的示例,在這些示例中,你可以在開(kāi)發(fā)機(jī)上運(yùn)行各種備份服務(wù),然后使用示例Node.js應(yīng)用程序代碼與它們交互。書(shū)中同時(shí)伴隨著大量的原理解釋和小問(wèn)題,足以充分滿足你的好奇心。
在閱讀本書(shū)的過(guò)程中,你將安裝并運(yùn)行許多不同的服務(wù),并且對(duì)于每一個(gè)服務(wù),你都將編寫(xiě)與它們交互的Node.js應(yīng)用程序代碼。本書(shū)著重強(qiáng)調(diào)了這些交互,并沒(méi)有把重心放在分析代碼上。
JavaScript 是一種很強(qiáng)大的語(yǔ)言,它能夠同時(shí)開(kāi)發(fā)前端和后端應(yīng)用。這便于我們避開(kāi)外圍技術(shù),把全部精力都投入語(yǔ)言學(xué)習(xí)中。許多人認(rèn)為只有使用Java或.NET等傳統(tǒng)企業(yè)平臺(tái)的工程師才會(huì)熟悉這些技術(shù),但其實(shí)JavaScript工程師也能夠受益于擁有第一手的技術(shù)經(jīng)驗(yàn)。
【讀者對(duì)象】
本書(shū)不會(huì)教你如何使用 Node.js。你應(yīng)該已經(jīng)擁有了 Node.js 的實(shí)戰(zhàn)經(jīng)驗(yàn)且能熟練使用JavaScript。也就是說(shuō),本書(shū)確實(shí)涵蓋了一些與 Node.js 和 JavaScript 相關(guān)的鮮為人知的高級(jí)概念,如“JavaScript的單線程特性”和“Node.js事件循環(huán)”。你還應(yīng)該熟悉HTTP的基礎(chǔ)知識(shí),至少使用過(guò)一個(gè)數(shù)據(jù)庫(kù)來(lái)持久化狀態(tài),并知道在運(yùn)行的Node.js進(jìn)程中維護(hù)狀態(tài)是多么容易但又多么危險(xiǎn)。
也許你已經(jīng)在一家擁有運(yùn)行后端服務(wù)的基礎(chǔ)設(shè)施的公司工作,并且渴望了解它是如何工作的以及你的Node.js應(yīng)用程序如何從中受益。或者,你有一個(gè)作為副業(yè)項(xiàng)目運(yùn)行的 Node.js
應(yīng)用程序,并且已經(jīng)厭倦了它的崩潰情況。你甚至可能是一家初創(chuàng)公司的CTO,并決心滿足不斷增長(zhǎng)的用戶群的需求。如果這些情況聽(tīng)起來(lái)很熟悉,那么本書(shū)很適合你。
【目標(biāo)】
Node.js通常用于構(gòu)建前端Web應(yīng)用程序。本書(shū)不涉及任何與前端開(kāi)發(fā)或?yàn)g覽器相關(guān)的主題。本書(shū)的目標(biāo)是讓你將后端Node.js服務(wù)與各種支持現(xiàn)代分布式系統(tǒng)的服務(wù)集成在一起。
當(dāng)你讀完本書(shū)的時(shí)候,你就會(huì)了解在生產(chǎn)環(huán)境中運(yùn)行 Node.js 服務(wù)所需的許多技術(shù)。例如,部署和擴(kuò)展應(yīng)用程序需要什么,如何使服務(wù)有冗余性和故障彈性,如何與其他分布式進(jìn)程進(jìn)行可靠的通信以及如何觀察應(yīng)用程序的運(yùn)行狀況。
當(dāng)然,僅僅通過(guò)閱讀本書(shū)就想成為專家不太現(xiàn)實(shí)。本書(shū)并未涉及調(diào)優(yōu)、分片和將可擴(kuò)展的 ELK 服務(wù)部署到生產(chǎn)環(huán)境中所需的操作。不過(guò),你將了解如何運(yùn)行本地的 ELK 實(shí)例,如何從 Node.js 服務(wù)向它發(fā)送日志,以及如何創(chuàng)建一個(gè)可視化數(shù)據(jù)面板來(lái)查看服務(wù)的運(yùn)行狀況(參見(jiàn)4.2節(jié))。
本書(shū)也許并未涵蓋你公司使用的所有技術(shù)。雖然第7章討論了 Kubernetes(一種編排應(yīng)用程序代碼部署的技術(shù)),但你的公司可能使用不同的解決方案,比如Apache Mesos。還有一種情況是你所用的是云環(huán)境中的Kubernetes版本,其底層實(shí)現(xiàn)對(duì)你來(lái)說(shuō)是黑箱。無(wú)論如何,通過(guò)學(xué)習(xí)分布式后端服務(wù)棧不同層級(jí)的工具,你將更容易理解可能遇到的其他技術(shù)棧。
【示例代碼】
可以從https://github.com/tlhunter/distributed-node下載補(bǔ)充材料(示例代碼、練習(xí)、勘誤等)。
這里的代碼是為了幫助你更好地理解本書(shū)的內(nèi)容。通常,可以在程序或文檔中使用本書(shū)中的代碼,而不需要聯(lián)系O’Reilly獲得許可,除非需要大段地復(fù)制代碼。例如,使用本書(shū)中所提供的幾個(gè)代碼片段來(lái)編寫(xiě)一個(gè)程序不需要得到我們的許可,但銷售或發(fā)布O’Reilly的示例代碼則需要獲得許可。引用本書(shū)的示例代碼來(lái)回答問(wèn)題也不需要許可,將本書(shū)中的很大一部分示例代碼放到自己的產(chǎn)品文檔中則需要獲得許可。
第1章 為什么要用分布式9
1.1 JavaScript的單線程特性9
1.2 Node.js 速覽13
1.3 Node.js的事件循環(huán)16
1.4 示例應(yīng)用程序21
第2章 協(xié)議26
2.1 使用HTTP請(qǐng)求和響應(yīng)27
2.2 使用GraphQL構(gòu)建API外觀39
2.3 使用gRPC進(jìn)行RPC通信46
第3章 擴(kuò)展54
3.1 集群模塊54
3.2 使用HAProxy實(shí)現(xiàn)反向代理61
3.3 SLA和負(fù)載測(cè)試72
第4章 可觀測(cè)性85
4.1 運(yùn)行環(huán)境85
4.2 ELK與日志87
4.3 Graphite、StatsD和Grafana度量指標(biāo)94
4.4 使用Zipkin進(jìn)行分布式請(qǐng)求跟蹤102
4.5 運(yùn)行狀況檢查110
4.6 使用 Cabot 進(jìn)行報(bào)警113
第5章 容器119
5.1 Docker簡(jiǎn)介121
5.2 容器化Node.js服務(wù)127
5.3 使用 Docker Compose進(jìn)行基本編排135
5.4 內(nèi)部Docker 注冊(cè)表140
第6章 部署145
6.1 使用 Travis CI 構(gòu)建流水線146
6.2 自動(dòng)化測(cè)試151
6.3 部署Heroku162
6.4 模塊、包和SemVer168
6.5 內(nèi)部npm注冊(cè)表179
第7章 容器編排184
7.1 Kubernetes 簡(jiǎn)介185
7.2 啟動(dòng)188
7.3 部署應(yīng)用程序192
7.4 服務(wù)發(fā)現(xiàn)199
7.5 修改部署204
第8章 彈性210
8.1 Node.js 進(jìn)程的終止210
8.2 構(gòu)建無(wú)狀態(tài)服務(wù)218
8.3 使用Memcached構(gòu)建外部緩存224
8.4 數(shù)據(jù)庫(kù)連接的彈性229
8.5 使用Knex進(jìn)行Schema 遷移238
8.6 冪等性和消息傳遞彈性248
8.7 彈性測(cè)試255
第9章 分布式基元259
9.1 ID 生成問(wèn)題259
9.2 Redis 簡(jiǎn)介262
9.3 Redis 操作263
9.4 尋求原子性272
9.5 事務(wù)274
9.6 Lua腳本276
第10章 安全性281
10.1 繁雜的代碼庫(kù)281
10.2 認(rèn)識(shí)攻擊面283
10.3 應(yīng)用程序配置287
10.4 升級(jí)依賴項(xiàng)292
10.5 升級(jí)Node.js298
附錄A 安裝HAProxy303
附錄B 安裝Docker305
附錄 C 安裝Minikube和Kubectl307