มาใช้ HTTP/2 Cloud Run เพื่อรองรับ Request > 32MB กัน
ถ้าหากใครใช้งาน Cloud Run มาพัฒนาแอพพลิเคชั่นที่ต้องมีการรองรับการอัพโหลดไฟล์ ถ้าหากใช้วิธี upload ผ่าน Cloud Run โดยตรงจะเจอข้อจำกัดของ Cloud Run ที่รองรับขนาดของ request สูงสุดที่ 32 MB และไม่สามารถเพิ่มได้
References: Request Maximum HTTP/1 request size, in MiB = 32 if using HTTP/1 server. No limit if using HTTP/2 server. (https://cloud.google.com/run/quotas)
แต่จะเห็นว่าไม่มีลิมิตนี้สำหรับ HTTP/2 server ดังนั้นมาลองดูกันว่าเงื่อนไขในการใช้ HTTP/2 server บน Cloud Run ต้องทำอย่างไรกันบ้าง?
- ทำการกำหนดค่า HTTP/2 end-to-end บน Cloud Run Service https://cloud.google.com/run/docs/configuring/http2
เนื่องจากปกติ Cloud Run จะทำการ downgrade HTTP/2 requests ที่ส่งไปถึง container ของเราไปเป็น HTTP/1 เสมอ เพื่อทำให้ไม่มีการ downgrade เราจะใช้ option HTTP/2 end-to-end นี้ - Container ที่ใช้จะต้องรับ requests ในรูปแบบ HTTP/2 cleartext (h2c) เนื่องจาก TLS ยังคงถูก terminate ด้วย Cloud Run เอง
แล้วเราจะวิธีทำ HTTP/2 h2c ได้อย่างไรบ้างหละ ตรงนี้เราสามารถลองดูได้จาก https://http2.github.io/ ไปที่หน้า Implementations จะเห็นรายการเช่น สำหรับ Node.js จะมี library node-spdy หรือ node-http2 ให้เลือกใช้
HTTP/2 h2c Node.js on Cloud Run Example
เมื่อพอจะเข้าใจสิ่งที่ต้องทำแล้ว มาลองดูตัวอย่างกันครับ
- Node.js node-http2 + express in h2c mode
- Deploy to Cloud Run with HTTP/2 end-to-end
#1 Node.js node-http2 + express in h2c mode
ไปที่ Directory ที่จะลองใช้ทดสอบ และเริ่ม intialize npm
npm init
ติดตั้ง express และ spdy
npm install express spdy
สร้าง index.js ตัวอย่างสำหรับ HTTP/2 h2c
const express = require('express');
const spdy = require('spdy');
const app = express();
const port = 8080;
var options = {
// **optional** SPDY-specific options
spdy: {
plain: true, // use plain http for http/2 h2c
ssl: false, // use plain http for http/2 h2c
protocols: ['h2','spdy/3.1', 'spdy/3', 'spdy/2','http/1.1', 'http/1.0'], // default protocols
}
};
app.get('/', (req, res) => {
res.send('Hello HTTP/2 h2c');
});
// Start the server on port 8080 or as defined in 'port'
// User spdy to create a server with options for http/2 h2c
var server = spdy.createServer(options, app);
server.listen(port);
ทดสอบรันบน local
node index.js
ทำการทดสอบการเรียก server ด้วย HTTP/2
curl -i --http2-prior-knowledge http://localhost:8080
Output ที่ได้ จะเห็นว่า protocol เป็น HTTP/2
HTTP/2 200
x-powered-by: Express
content-type: text/html; charset=utf-8
content-length: 16
etag: W/"10-x/UNxuT+4S79iOZodzRjYdEdVGQ"
Hello HTTP/2 h2c
#2 Deploy to Cloud Run with HTTP/2 end-to-end
ทำการเพิ่ม Procfile สำหรับ Cloud Run (buildpack) ที่จะกำหนด Entrypoint ในการ start
หรืออีกทางเลือกคือการเพิ่ม start scripts ลงใน package.json ก็ได้เช่นกัน
Procfile method
reference https://cloud.google.com/docs/buildpacks/nodejs#application_entrypoint
cat <<EOF > Procfile
web: node index.js
EOF
Package.json start scripts
reference https://cloud.google.com/run/docs/quickstarts/jobs/build-create-nodejs
...
"scripts": {
"start": "node index.js"
}
...
ทำการ Deploy ไปยัง Cloud Run โดยมี option ที่สำคัญคือ
test-http2-nodejs คือชื่อของเซอวิส
— source . กำหนดให้อัพโหลด source code และทำการ build ให้โดยอัตโนมัติ ซึ่งในกรณีนี้จะใช้ buildpack เนื่องจากเราไม่ได้ทำ Dockerfile ไว้
— use-http2 กำหนดให้ใช้งาน HTTP/2 end-to-end
— allow-unauthenticated กำหนดให้ไม่ต้องมีการเช็ค run.invoker permission สำหรับการทดสอบ
gcloud run deploy test-http2-nodejs --source . --use-http2 --allow-unauthenticated
เมื่อ deploy เสร็จแล้วสามารถเช็ค url ของ cloud run ได้โดย
URL=$(gcloud run services describe test-http2-nodejs --format 'value(status.url)')
echo $URL
ทดสอบด้วย curl
curl -i $URL
Output จะเห็นว่ารองรับเป็น HTTP/2 แล้ว
โดยถ้าหากเราเปิด option HTTP/2 end-to-end บน Cloud Run แต่ container ไม่ได้รองรับ HTTP/2 h2c จะเรียกเซอวิสไม่สำเร็จ เนื่องจาก option นี้จะ force ให้ Cloud Run ไม่ทำการ downgrade to HTTP/1 และต้องเชื่อมต่อเป็น HTTP/2 h2c เท่านั้น
HTTP/2 200
x-powered-by: Express
content-type: text/html; charset=utf-8
content-length: 16
...
Hello HTTP/2 h2c
สรุป
เมื่อเราทำ HTTP/2 end-to-end แล้ว เราจะได้ประโยชน์และลดข้อจำกัดเช่น
- Inbound requests per second จำกัดที่ 800 บน HTTP/1 แต่จะไม่มีข้อจำกัดนี้บน HTTP/2 container ports
- Maximum HTTP/1 request size คือ 32 MiB แต่จะไม่มีข้อจำกัดนี้บน HTTP/2 server
reference https://cloud.google.com/run/quotas