微服务网关(五)grpc代理模块
GRPC是谷歌出品的一个高性能、开源、通用的RPC框架,基于HTTP/2标准设计,支持普通RPC也支持双向流式传递,相对于thrift连接,它可以多路复用,可传递header头数据
在http请求当中我们可以设置header用来传递数据,grpc底层采用http2协议也是支持传递数据的,采用的是metadata。http传递的是文本形式的文件
Metadata 对于 gRPC 本身来说透明, 它使得 client 和 server 能为对方提供本次调用的信息。rpc传递的是二进制文件
就像一次 http 请求的 RequestHeader 和 ResponseHeader,http header 的生命周期是一次 http 请求, Metadata 的生命周期则是一次 RPC 调用。
GRPC透明代理
不需要实现grpc的IDL结构体
GRPC代理服务器的代理实现:
请求流程:
一次grpc服务端的启停
整体上与TCP类似,不过多赘述,只举出不同之处的主体代码
grpcserver.go
func GrpcServerRun() {
....
go func(serviceDetail *dao.ServiceDetail) {
addr := fmt.Sprintf(":%d", serviceDetail.GRPCRule.Port)
rb, err := dao.LoadBalancerHandler.GetLoadBalancer(serviceDetail)
....
lis, err := net.Listen("tcp", addr)
....
//设置负载均衡策略
grpcHandler := reverse_proxy.NewGrpcLoadBalanceHandler(rb)
s := grpc.NewServer(
grpc.ChainStreamInterceptor(
grpc_proxy_middleware.GrpcFlowCountMiddleware(serviceDetail),
grpc_proxy_middleware.GrpcFlowLimitMiddleware(serviceDetail),
grpc_proxy_middleware.GrpcJwtAuthTokenMiddleware(serviceDetail),
grpc_proxy_middleware.GrpcJwtFlowCountMiddleware(serviceDetail),
grpc_proxy_middleware.GrpcJwtFlowLimitMiddleware(serviceDetail),
grpc_proxy_middleware.GrpcWhiteListMiddleware(serviceDetail),
grpc_proxy_middleware.GrpcBlackListMiddleware(serviceDetail),
grpc_proxy_middleware.GrpcHeaderTransferMiddleware(serviceDetail),
),
grpc.UnknownServiceHandler(grpcHandler),
)
....
//开启服务
if err := s.Serve(lis); err != nil {
log.Fatalf(" [INFO] grpc_proxy_run %v err:%v\n", addr, err)
}
}(tempItem)
}
}
func GrpcServerStop() {
for _, grpcServer := range grpcServerList {
grpcServer.GracefulStop()
log.Printf(" [INFO] grpc_proxy_stop %v stopped\n", grpcServer.Addr)
}
}
grpc_reverse_proxy.go
func NewGrpcLoadBalanceHandler(lb load_balance.LoadBalance) grpc.StreamHandler {
return func() grpc.StreamHandler {
nextAddr, err := lb.Get("")
if err != nil {
log.Fatal("get next addr fail")
}
director := func(ctx context.Context, fullMethodName string) (context.Context, *grpc.ClientConn, error) {
c, err := grpc.DialContext(ctx, nextAddr, grpc.WithInsecure())
md, _ := metadata.FromIncomingContext(ctx)
outCtx, _ := context.WithCancel(ctx)
outCtx = metadata.NewOutgoingContext(outCtx, md.Copy())
return outCtx, c, err
}
return proxy.TransparentHandler(director)
}()
}