【问题标题】:gRPC GO Single Generic Service HandlergRPC GO 单一通用服务处理程序
【发布时间】:2023-03-07 19:01:01
【问题描述】:

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

以下是我目前得到的结果

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

【问题讨论】:

    标签: go grpc


    【解决方案1】:

    得到它的工作,感谢protoreflect

    没有错误处理的工作示例

    //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
    }
    

    【讨论】:

      猜你喜欢
      • 2018-01-09
      • 2020-06-25
      • 1970-01-01
      • 1970-01-01
      • 2017-04-10
      • 1970-01-01
      • 2023-03-12
      • 2019-01-09
      • 2018-08-20
      相关资源
      最近更新 更多