Skip to main content
Version: 2.8.x(Latest)

Client Implementation


The API Gateway acts as a gRPC client, while each microservice acts as a gRPC server. We'll define the gRPC client in our controller properties for later use.

The client is defined using grpcx.Client.MustNewGrpcClientConn(service, opts...).

app/gateway/internal/controller/user/user_new.go

package user  

import (
"github.com/gogf/gf/contrib/rpc/grpcx/v2"
"proxima/app/gateway/api/user"
v1 "proxima/app/user/api/account/v1"
)

type ControllerV1 struct {
AccountClient v1.AccountClient
}

func NewV1() user.IUserV1 {
var conn = grpcx.Client.MustNewGrpcClientConn("user")

return &ControllerV1{
AccountClient: v1.NewAccountClient(conn),
}
}

app/gateway/internal/controller/words/words_new.go

package words  

import (
"github.com/gogf/gf/contrib/rpc/grpcx/v2"
"proxima/app/gateway/api/words"
v1 "proxima/app/word/api/words/v1"
)

type ControllerV1 struct {
WordsClient v1.WordsClient
}

func NewV1() words.IWordsV1 {
var conn = grpcx.Client.MustNewGrpcClientConn("word")

return &ControllerV1{
WordsClient: v1.NewWordsClient(conn),
}
}

Interceptors


Currently, our client doesn't have timeout handling, and gRPC's default timeout threshold is very high. If the gRPC server, etcd service, or network encounters issues, the API Gateway could hang indefinitely. Let's add a timeout interceptor to handle these situations.

Defining the Interceptor

The timeout mechanism is simple, implemented using Go's context.

app/gateway/utility/grpc.go

package utility  

import (
"context"
"time"
"google.golang.org/grpc"
)

func GrpcClientTimeout(ctx context.Context, method string, req, reply interface{},
cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption,
) error {
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
defer cancel()

err := invoker(ctx, method, req, reply, cc, opts...)
return err
}

Using the Interceptor

app/gateway/internal/controller/user/user_new.go

package user  

import (
"github.com/gogf/gf/contrib/rpc/grpcx/v2"
"proxima/app/gateway/api/user"
"proxima/app/gateway/utility"
v1 "proxima/app/user/api/account/v1"
)

type ControllerV1 struct {
AccountClient v1.AccountClient
}

func NewV1() user.IUserV1 {
var conn = grpcx.Client.MustNewGrpcClientConn("user", grpcx.Client.ChainUnary(
utility.GrpcClientTimeout,
))

return &ControllerV1{
AccountClient: v1.NewAccountClient(conn),
}
}

app/gateway/internal/controller/words/words_new.go

package words  

import (
"github.com/gogf/gf/contrib/rpc/grpcx/v2"
"proxima/app/gateway/api/words"
"proxima/app/gateway/utility"
v1 "proxima/app/word/api/words/v1"
)

type ControllerV1 struct {
WordsClient v1.WordsClient
}

func NewV1() words.IWordsV1 {
var conn = grpcx.Client.MustNewGrpcClientConn("word", grpcx.Client.ChainUnary(
utility.GrpcClientTimeout,
))

return &ControllerV1{
WordsClient: v1.NewWordsClient(conn),
}
}