客户端
业务网关相当于gRPC
客户端,各个微服务相当于gRPC
服务端。我们将在控制器属性里,定义gRPC client
,供后续使用。
定义client
由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),
}
}
拦截器
当前客户端没有超时处理,gRPC
的默认超时时间阈值又非常大。如果gRPC
服务端、etcd
服务,或者网络出现异常,业务网关会无限卡死。我们来添加超时拦截器,以应对这种情况。
定义拦截器
超时机制很简单,通过Go
的上下文提供。
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
}
调用拦截器
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),
}
}