Я пытаюсь создать небольшой прототип для прокси-службы gRPC (на основе github.com/buaazp/fasthttprouter
), которая выполняет вызовы к бэкенду gRPC
Мой прототип основан на примере helloworld gRPC :
package main
import (
pb "../proto/helloworld"
"context"
"fmt"
"github.com/buaazp/fasthttprouter"
grpcpool "github.com/processout/grpc-go-pool"
"github.com/valyala/fasthttp"
"google.golang.org/grpc"
"log"
"os"
"time"
)
const (
address = "localhost:50051"
)
func main() {
// grpc client pool
var factory grpcpool.Factory
factory = func() (*grpc.ClientConn, error) {
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
log.Fatalf("Failed to start gRPC connection: %v", err)
}
return conn, err
}
pool, err := grpcpool.New(factory, 5, 5, time.Second)
if err != nil {
log.Fatalf("Failed to create gRPC pool: %v", err)
}
// routers and handlers
router := fasthttprouter.New()
router.GET("/without_gr", func(ctx *fasthttp.RequestCtx) {
// ab -c 100 -n 1000 http://127.0.0.1:1111/without_gr
// 8500 rps without goroutine
conn, _ := pool.Get(ctx)
defer conn.Close()
if err != nil {
_, _ = fmt.Fprintf(ctx, "Get pool failed")
return
}
client := pb.NewGreeterClient(conn.ClientConn)
_, _ = client.SayHello(ctx, &pb.HelloRequest{Name: "Pool ON"})
_, _ = fmt.Fprintf(ctx, "Welcome to my website! Pool ON")
})
router.GET("/with_gr", func(ctx *fasthttp.RequestCtx) {
go func(ctx *fasthttp.RequestCtx) {
// ab -c 100 -n 1000 http://127.0.0.1:1111/with_gr
// 14000 rps with goroutine
conn, _ := pool.Get(ctx)
defer conn.Close()
if err != nil {
_, _ = fmt.Fprintf(ctx, "Get pool failed")
return
}
client := pb.NewGreeterClient(conn.ClientConn)
_, _ = client.SayHello(ctx, &pb.HelloRequest{Name: "Pool ON"})
_, _ = fmt.Fprintf(ctx, "Welcome to my website! Pool ON")
}(ctx)
})
_ = fasthttp.ListenAndServe(":1111", router.Handler)
}
Результаты:
- http-вызов с goroutine дает мне 14K rps
- http-вызов без goroutine только 8K rps
Мои вопросы:
- Это правильный пример?
- Нужно ли мне запускать все вызовы API с упаковкой goroutine?