首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >gRPC GO单一通用服务处理程序

gRPC GO单一通用服务处理程序
EN

Stack Overflow用户
提问于 2021-01-04 18:30:57
回答 1查看 188关注 0票数 1

我已经使用protoreflect编写了http- to -gRPC-gateway。但我没有看到任何简单的选择来实现反向gRPC到HTTP网关。其中一个想法是将GRPC暴露给外部,但使用自定义网关通过MessageQ调用内部微服务,以避免负载平衡,发现服务,并可以转换GRPC流持久或使用反射来调用方法,而不是使用生成的服务器存根

下面是我到目前为止所得到的

代码语言:javascript
复制
func main() {
    lis, err := net.Listen("tcp", ":9091")
    grpcServer := grpc.NewServer(grpc.UnknownServiceHandler(GenericHandler))
    //pb.RegisterGreeterServer(grpcServer, &TestService{})
    grpcServer.Serve(lis)
}

func GenericHandler(srv interface{}, stream grpc.ServerStream) error {
    fullMethodName, ok := grpc.MethodFromServerStream(stream)
    log.Printf("Method: %v, %v\n", fullMethodName, ok)
    //how to get protobuf payload from stream
    //Response:=Invoke Method via Reflection or http or MessageQueue - passing either the raw protocal buffer or as json
    //how to return Response
    return nil
}

我看到实现这一点的唯一方法是理解并重新实现实际的处理程序processUnaryRPC

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-01-13 17:29:53

多亏了protoreflect,它才能正常工作

不带错误处理的工作样本

代码语言:javascript
复制
//Parse protofile, create grpc.ServiceDesc, register
func (s *GRPCService) LoadSpec(protoFileName string) {
    p := protoparse.Parser{}
    fdlist, _ := p.ParseFiles(protoFileName)
    for _, fd := range fdlist {
        for _, rsd := range fd.GetServices() {
            s.sdMap[rsd.GetName()] = rsd
            gsd := grpc.ServiceDesc{ServiceName: rsd.GetName(), HandlerType: (*interface{})(nil)}
            for _, m := range rsd.GetMethods() {
                gsd.Methods = append(gsd.Methods, grpc.MethodDesc{MethodName: m.GetName(), Handler: s.Handler})
            }
            s.grpcServer.RegisterService(&gsd, s)
        }
    }
}

func (s *GRPCService) Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
    stream := grpc.ServerTransportStreamFromContext(ctx)
    arr := strings.Split(stream.Method(), "/")
    serviceName := arr[1]
    methodName := arr[2]
    service := s.sdMap[serviceName]
    method := service.FindMethodByName(methodName)
    input := dynamic.NewMessage(method.GetInputType())

    dec(input)
    jsonInput, err := input.MarshalJSON()
    log.Printf("Input:%s Err:%v \n", jsonInput, err)
    //jsonOutput:=invokeServiceViaReflectionOrHttp(jsonInput)
    jsonOutput := `{"message":"response"}`

    output := dynamic.NewMessage(method.GetOutputType())
    output.UnmarshalJSON([]byte(jsonOutput))
    return output, nil
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65561125

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档