當(dāng)我們談部署時(shí),我們?cè)谡勈裁矗?/h1>

計(jì)算機(jī)網(wǎng)絡(luò)把各地的計(jì)算機(jī)連接了起來(lái),只要有一臺(tái)可以上網(wǎng)的終端,比如手機(jī)、電腦,就可以訪(fǎng)問(wèn)互聯(lián)網(wǎng)上任何一臺(tái)服務(wù)器的資源(包括靜態(tài)資源和動(dòng)態(tài)的服務(wù))。
作為開(kāi)發(fā)者的我們,就是這些資源、服務(wù)的提供者,把資源上傳到服務(wù)器,并把服務(wù)跑起來(lái)的過(guò)程就叫做部署。

代碼部分的部署,需要先經(jīng)過(guò)構(gòu)建,也就是編譯打包的過(guò)程,把產(chǎn)物傳到服務(wù)器。
最原始的部署方式就是在本地進(jìn)行 build,然后把產(chǎn)物通過(guò) FTP 或者 scp(基于 SSH 的遠(yuǎn)程拷貝文件拷貝) 傳到服務(wù)器上,如果是后端代碼還需要重啟下服務(wù)。

每個(gè)人單獨(dú)構(gòu)建上傳,這樣不好管理,也容易沖突,所以現(xiàn)在都會(huì)用專(zhuān)門(mén)的平臺(tái)來(lái)做這件事構(gòu)建和部署,比如 jenkins。
我們代碼會(huì)提交到 gitlab 等代碼庫(kù),然后 jenkins 從這些代碼庫(kù)里把代碼下載下來(lái)進(jìn)行 build,再把產(chǎn)物上傳到服務(wù)器上。
流程和直接在本地構(gòu)建上傳差不多,只不過(guò)這樣方便管理沖突、歷史等,還可以跨項(xiàng)目復(fù)用一些東西。

構(gòu)建、部署的過(guò)程最開(kāi)始是通過(guò) shell 來(lái)寫(xiě),但寫(xiě)那個(gè)的要求還是很高的,很少人會(huì)寫(xiě)(我就不咋會(huì))。后來(lái)就支持了可視化的編排,可以被編排的這個(gè)構(gòu)建、部署的流程叫做流水線(xiàn) pipeline。

比如這是 jenkins 的 pipeline 的界面:

除了構(gòu)建、部署外,也可以加入一些自動(dòng)化測(cè)試、靜態(tài)代碼檢查等任務(wù)。
這種自動(dòng)化了的構(gòu)建、部署流程就叫做 CI(持續(xù)集成)、CD(持續(xù)部署)。
我們現(xiàn)在還是通過(guò) scp / FTP 來(lái)上傳代碼做的部署,但是不同代碼的運(yùn)行環(huán)境是不同的,比如 Node.js 服務(wù)需要安裝 node,Java 服務(wù)需要安裝 JRE 等,只把代碼傳上去并不一定能跑起來(lái)。
那怎么辦呢?怎么保證部署的代碼運(yùn)行在正確的環(huán)境?
把環(huán)境也給管理起來(lái),作為部署信息的一部分不就行了?
現(xiàn)在流行的容器技術(shù)就是做這個(gè)的,比如 docker,可以把環(huán)境信息和服務(wù)啟動(dòng)方式放到 dockerfile 里,build 產(chǎn)生一個(gè)鏡像 image,之后直接部署這個(gè) docker image 就行。
比如我們用 nginx 作為靜態(tài)服務(wù)器的時(shí)候,dockerfile 可能是這樣的:
FROM nginx:alpine
COPY /nginx/ /etc/nginx/
COPY /dist/ /usr/share/nginx/html/
EXPOSE 80
這樣就把運(yùn)行環(huán)境給管理了起來(lái)。
所以,現(xiàn)在的構(gòu)建產(chǎn)物不再是直接上傳服務(wù)器,而是生成一個(gè) docker image,上傳到 docker registry,然后把這個(gè) docker image 部署到服務(wù)器。


還有一個(gè)問(wèn)題,現(xiàn)在前端代碼、后端代碼都部署在了我們的服務(wù)器上,共享服務(wù)器的網(wǎng)絡(luò)帶寬,其中前端代碼是不會(huì)變動(dòng)的、流量卻很大,這樣使得后端服務(wù)的可用帶寬變小、支持的并發(fā)量下降。
能不能把這部分靜態(tài)資源的請(qǐng)求分離出去呢?最好能部署到離用戶(hù)近一點(diǎn)的服務(wù)器,這樣訪(fǎng)問(wèn)更快。
確實(shí)可以,這就是 CDN 做的事情。
網(wǎng)上有專(zhuān)門(mén)的 CDN 服務(wù)提供商,它們有很多分散在各地的服務(wù)器,可以提供靜態(tài)資源的托管。這些靜態(tài)資源最終還是從我們的靜態(tài)資源服務(wù)器來(lái)拿資源的,所以我們的靜態(tài)資源服務(wù)器叫做源站。但是請(qǐng)求一次之后就會(huì)緩存下來(lái),下次就不用再請(qǐng)求源站了,這樣就減輕了我們服務(wù)器的壓力,還能加速用戶(hù)請(qǐng)求靜態(tài)資源的速度。

這樣就解決了靜態(tài)資源分去了太多網(wǎng)絡(luò)帶寬的問(wèn)題,而且還加速了資源的訪(fǎng)問(wèn)速度。
此外,靜態(tài)資源的部署還要考慮順序問(wèn)題,要先部署頁(yè)面用到的資源,再部署頁(yè)面,還有,需要在文件名加 hash 來(lái)觸發(fā)緩存更新等,這些都是更細(xì)節(jié)的問(wèn)題。
這里說(shuō)的都是網(wǎng)頁(yè)的部署方式,對(duì)于 APP/小程序它們是有自己的服務(wù)器和分發(fā)渠道的,我們構(gòu)建完之后不是部署,而是在它們的平臺(tái)提交審核,審核通過(guò)之后由它們負(fù)責(zé)部署和分發(fā)。
總結(jié)
互聯(lián)網(wǎng)讓我們能夠用手機(jī)、PC 等終端訪(fǎng)問(wèn)任何一臺(tái)服務(wù)器的資源、服務(wù)。而提供這些資源、服務(wù)就是我們開(kāi)發(fā)者做的事情。把資源上傳到服務(wù)器上,并把服務(wù)跑起來(lái),就叫做部署。
對(duì)于代碼,我們可以本地構(gòu)建,然后把構(gòu)建產(chǎn)物通過(guò) FTP/scp 等方式上傳到服務(wù)器。
但是這樣的方式不好管理,所以我們會(huì)有專(zhuān)門(mén)的 CI/CD 平臺(tái)來(lái)做這個(gè),比如 jenkins。
jenkins 支持 pipeline 的可視化編排,比寫(xiě) shell 腳本的方式易用很多,可以在構(gòu)建過(guò)程中加入自動(dòng)化測(cè)試、靜態(tài)代碼檢查等步驟。
不同代碼運(yùn)行環(huán)境不同,為了把環(huán)境也管理起來(lái),我們會(huì)使用容器技術(shù),比如 docker。把環(huán)境信息寫(xiě)入 dockerfile,然后構(gòu)建生成 docker image,上傳到 registry,之后部署這個(gè) docker image 就行。
靜態(tài)資源和動(dòng)態(tài)資源共享服務(wù)器的網(wǎng)絡(luò)帶寬,為了減輕服務(wù)器壓力、也為了加速靜態(tài)資源的訪(fǎng)問(wèn),我們會(huì)使用 CDN 來(lái)對(duì)靜態(tài)資源做加速,把我們的靜態(tài)服務(wù)器作為源站。第一個(gè)靜態(tài)資源的請(qǐng)求會(huì)請(qǐng)求源站并緩存下來(lái),之后的請(qǐng)求就不再需要請(qǐng)求源站,這樣就減輕了源站的壓力。此外,靜態(tài)資源的部署還要考慮順序、緩存更新等問(wèn)題。
對(duì)于網(wǎng)頁(yè)來(lái)說(shuō)是這樣,APP/小程序等不需要我們負(fù)責(zé)部署,只要在它們的平臺(tái)提交審核,然后由它們負(fù)責(zé)部署和分發(fā)。
當(dāng)我們?cè)谡劜渴鸬臅r(shí)候,主要就是在談這些。















 
 
 










 
 
 
 