มาใช้ HTTP/2 Cloud Run เพื่อรองรับ Request > 32MB กัน

Nuttee Jirattivongvibul
Google Cloud Thailand
3 min readNov 29, 2023
“Large Requests” created from Google Bard

ถ้าหากใครใช้งาน 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 ต้องทำอย่างไรกันบ้าง?

  1. ทำการกำหนดค่า 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 นี้
  2. 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

เมื่อพอจะเข้าใจสิ่งที่ต้องทำแล้ว มาลองดูตัวอย่างกันครับ

  1. Node.js node-http2 + express in h2c mode
  2. 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

--

--