原文:Easy HTTP/2 Server with Node.js and Express.js
作者:Azat Mardan
代碼:http2-express
什麼是 HTTP/2
現代網際網路的
TCP/IP
協定釋出于1975年,這項技術在41年前是多麼令人驚訝。自它釋出開始大部分形式,我們使用
HTTP
和 後續接任者
HTTP/1.1
來實作用戶端和服務端的通訊。它能很不錯的傳輸
Web
,但今時今日的開發者建立網站的方式已經發生了巨大的改變。存在各式各樣的外部資源連結例如圖檔、
CSS
檔案、
JavaScript
資源。資源的種類數量隻會持續增長。
HTTP/2
是針對表現一直不錯的舊協定
HTTP
自從1991年釋出以來這15年的第一次大的更新改動!它為優化現代浏覽器而生。性能更加優越而且不用使用複雜的行為例如
域名分片
(通過多個域名發送資源)或者資源檔案合并`(提供一個整合的大資源而不是多個小資源)
HTTP/2
是目前
web
的新标準,其雛形是 Google 的
SPDY
協定。目前已經被大多數主流浏覽器支援,且很多網站已經通過該協定實作。例如通路 Yahoo 的
Flickr
在使用的是
HTTP/2
協定(截圖時間為2016年7月).
HTTP/2 的優勢和注意事項
HTTP/2
和
HTTP/1.1
的使用沒什麼差別,仍然可以在
body
中使用類
xml
的文法,使用
header
協定頭字段, 狀态碼, cookies, methods, URLs, 等等。開發者熟悉使用的東西都還可以繼續在
HTTP/2
使用。
HTTP/2
的優勢如下:
- 多路複用傳輸(Multiplexing):允許浏覽器在單個TCP連接配接中包含多個請求,進而使浏覽器能夠并行地請求所有的資源;
- 伺服器推送(Server push):伺服器可以在浏覽器知道需要該資源前,推送給浏覽器(如:CSS、JS、Image),進而通過減少請求數量來加速頁面加載時間;
- 流傳輸優先級(Stream priority):允許浏覽器去控制資源的加載優先級,例如,浏覽器先請求
渲染再去加載其他的HTML
和CSS
檔案;JS
- 頭部壓縮(Header compression):
請求的頭部總是重複一樣的内容,而HTTP/1.1
則強制對所有請求的頭部進行了去重壓縮;HTTP/2
- 實際的強制加密(De facto mandatory encryption):雖然加密不是硬性要求的,但是大多數浏覽器隻支援
上的TLS(HTTPS)
。HTTP/2
雖然目前對于
HTTP/2
還不能完全滿足一些苛求,但是直到更好的技術出現以前,目前是一項明顯的技術進步。讓我們來看看,作為
Web
開發者需要了解的必要知識。大部分适用于
HTTP/1.1
的優化技巧在
HTTP/2
中變成多餘的,其中一些甚至反而會影響
HTTP/2
上的網站性能,例如:
- 資源檔案合并;
- 你也應該停止使用精靈圖(image sprites)、CSS和JS打包,因為隻要其中一小部分有改動就會影響用戶端的緩存的作用;在
協定上更好的方式是使用多個的小檔案,而不是一個大檔案。HTTP/2
- 作者希望前端建構工具,如
、Grunt
、Gulp
将會是以特性被放棄使用,他們使Webpack
開發更高的複雜度,極高的學習曲線,以及管理項目的依賴關系。Web
- 另一個适用于
不适用于HTTP/1.1
的是,域名分片(為了繞過TCP并行請求數量限制)。雖然它不一定在所有情況下有害,但對于HTTP/2
的多路複用傳輸,這樣做也已經沒好處了。之是以建議不在HTTP/2
使用域名分片,還因為每個域名會帶來額外的查詢負載。如果真的有需要,那麼更好的方式是解析多個域名到同一個IP,而且保證你使用的是通配符證書或整合了多域名的證書,進而減少域名查詢的時間。HTTP/2
若想了解更多關于
HTTP/2
的介紹,可以看看官網。
Node.js 搭建 HTTP/2
現在,讓我們看看怎麼通過
Node.js
搭建
HTTP/2
伺服器。
部署證書
建立一個新檔案夾以及自己簽發的
SSL
證書。
$ mkdir http2-express
$ cd http2-express
$ openssl genrsa -des3 -passout pass:x -out server.pass.key
...
$ openssl rsa -passin pass:x -in server.pass.key -out server.key
writing RSA key
$ rm server.pass.key
$ openssl req -new -key server.key -out server.csr
...
Country Name ( letter code) [AU]:US
State or Province Name (full name) [Some-State]:California
...
A challenge password []:
...
$ openssl x509 -req -sha256 -days -in server.csr -signkey server.key -out server.crt
當你通路伺服器的時候,因為浏覽器預設不信任自己簽發的證書,請確定選擇 “進階” 和 “繼續通路 localhost (不安全)” 或者将 localhost 設定成不安全通路的例外。
初始化、依賴、入口
通過
npm
,初始化項目
package.json
,安裝依賴
spdy
和
express
:
npm init
npm i express spdy --save
建立應用的入口檔案
index.js
,主要是引用以及執行個體化
const port =
const spdy = require('spdy')
const express = require('express')
const path = require('path')
const fs = require('fs')
const app = express()
定義 Express.js 的 route
實作
Express.js
的
route
app.get('*', (req, res) => {
res
.status()
.json({message: 'ok'})
})
設定證書以及啟動 Server
通過
fs.readFileSync()
讀驗證書
const options = {
key: fs.readFileSync(__dirname + '/server.key'),
cert: fs.readFileSync(__dirname + '/server.crt')
}
然後,設定證書選項到
Express
對象:
spdy
.createServer(options, app)
.listen(port, (error) => {
if (error) {
console.error(error)
return process.exit()
} else {
console.log('Listening on port: ' + port + '.')
}
})
最後,
node .
啟動伺服器
檢查結果
通過浏覽器的開發者工具檢視協定,就如剛剛我們檢視
Yahoo 的 Flickr
協定一樣。
可以看到,使用 Node.js 和 Express.js 配合庫 node-spdy 實作
HTTP/2
簡單易懂。大多數情況下,對你的業務代碼是基本不需要修改的,想必,你的網站也已經使用了
HTTPS/SSL
(除非你的伺服器隻提供靜态資源,否則你應該使用安全的
HTTPS/SSL
),即使是不使用 HTTP/2 你也可以替換 HTTP/1.1 而使用 SPDY
當然,在 Node.js 的大環境中,有很多的庫,不隻是 node-spdy 提供
HTTP/2
實作,例如:node-http2
結語
HTTP/2
提供了更多更優的好處,而且不用使用複雜的優化技巧。開始享受
HTTP/2
給你帶來的這些好處。展望光明的未來!
PS:
本文源代碼位址在 http2-express
我的部落格