I am currently benchmarking a Google cloud serverless container service: Cloud Run.
Based on Google documentation, I tried to implement a simple Golang web server:
package main
import (
"fmt"
"log"
"net/http"
"os"
)
func handler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}
func main() {
log.Print("helloworld: starting server...")
http.HandleFunc("/", handler)
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
log.Printf("helloworld: listening on port %s", port)
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
}
I packaged it with this Dockerfile using gcloud builds submit --tag gcr.io/PROJECT-ID/helloworld:
FROM golang:alpine AS builder
#Set necessary environment variables needed for our image
ENV GO114MODULE=on \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64
# Move to working directory /build
WORKDIR /build
COPY main.go .
RUN go mod init main.go
# Build the application
RUN go build -o main .
# Build a small image
FROM alpine
COPY --from=builder /build/main /server
RUN apk add --no-cache ca-certificates openssl
# Run the web service on container startup.
CMD ["/server"]
When I benchmarked my Cloud Run Service using Bombardier
./bombardier -c 3 -d 500s -l -r 80 https://url.com
The service scales to 5 cpu-s/s (5 containers) to handle 80 req/s on 3 connections. It seems strange because I did set the concurrency to 80 so I should only have 1 container (at most 2-3 for fault tolerance).
Based on this results, various connections and request per seconds parameters were tested and even an other language (Python). The ratio between requests and containers looks to remain between 10 and 15 req/s per container.
I benchmarked the golang server and the container locally, both were able to handle way more than 80 req/s.
Am I missing something here ? Or is it some Google hidden limitations ?