【问题标题】:Golang grpc.server: Understanding notions of server, and servicesGolang grpc.server:理解服务器和服务的概念
【发布时间】:2021-03-26 16:14:03
【问题描述】:

我试图在 gRPC、Protobuf 的上下文中理解侦听器、服务器和服务的概念。

让我们使用https://grpc.io/docs/languages/go/basics/ 上的示例作为参考。 这里有

  1. 听众:lis
  2. gRPC 服务器:grpcServer := grpc.NewServer()
  3. 服务:RouteGuide 服务

看来我们还可以在同一服务器上注册多个服务。

也就是说,除了RouteGuide Service,我们还可以说SomeOther Service,SomeOtherOther Service。

我们可以注册所有这三个,并期望服务器能够提供属于这三个服务(RouteGuide、SomeOther、SomeOtherOther)的方法。

假设 RouteGuide、SomeOther、SomeOtherOther 都有自己的特定于它们的 proto 文件。并且所有的原型都在同一个命名空间中(package 值)。

grpcServer := grpc.NewServer(opts...)

newRouteGuideService := pb.NewRouteGuideServer()
pb.RegisterRouteGuideServer(grpcServer, newRouteGuideService)

someOtherService := pb.NewSomeOtherServer()
pb.RegisterSomeOtherServer(grpcServer, someOtherService)

someOtherOtherService := pb.NewSomeOtherOtherServer()
pb.RegisterSomeOtherOtherService(grpcServer, someOtherOtherService)

 lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", 80))
grpcServer.Serve(lis)

似乎“服务器”一词在这里被过度使用了。 不仅是 grpcServer,RouteGuide、SomeOther 和 SomeOtherOther 也被称为 Server。

我正在尝试弄清楚如何建模或理解这些概念。

我们可以说,服务器gRPCServer通过监听器lis监听80端口,可以服务于它注册的三个服务RouteGuide、SomeOther、SomeOtherOther(gRPCServer)? 拥有一台服务器服务多个服务是否容易出错? 使用具有多个服务的一台服务器时要记住哪些注意事项?

【问题讨论】:

    标签: go grpc grpc-go protobuf-go


    【解决方案1】:

    侦听器侦听给定端口上的连接,当客户端连接时,它会创建一个新的 goroutine 来处理该特定会话。当 goroutine 处理特定的客户端连接时,侦听器继续在端口上侦听新的传入连接。

    会话只是侦听来自已连接客户端的请求并将它们分派给已注册的服务之一。传入的请求包括服务的名称、要调用的函数以及该函数的参数。当服务处理请求时,会将响应发送回客户端。

    因此,正如您所说,服务器侦听端口并可以通过该端口为所有注册服务提供服务。这不容易出错,并且与拥有一个定义所有这些功能的注册服务没有什么不同。

    【讨论】:

    • 感谢您的回答。请记住,我对命名空间冲突等方面感到好奇。例如,这些不同的服务必须是同一个包的一部分吗?
    • 包装在操作方面无关紧要,它只是为符号创建一个命名空间。如果它们是松散相关或不相关的,请将它们作为单独的包保存。如果它们紧密耦合,那么您可以将它们合并到一个包中。应该使用重用和隔离模式来决定打包。
    【解决方案2】:

    请记住,Golang 是组合式的。因此,如果您以简化的伪方式进行布局:

    // Simplified Example
    //The interfaces would be made by your proto definition
    type Service1 interface { 
       // does service 1 stuff
       ServiceHandler1()
       ServiceHandler2()
    }
    
    type S1 struct{}
    func(*S1) ServiceHandler1() {
      //do svc1 stuff
    }
    
    type S2 struct{}
    func(*S2) ServiceHandler2() {
      //do svc2 stuff
    }
    
    type S3 struct{
      // compose s1, s2
      S1
      S2
    }
    

    服务器是具有监听器的 GRPC 的顶层,然后您注册满足您的 GRPC 原型定义所需接口的服务。

    所以在上面的例子中,我可以在 proto rpc 中定义 ServiceHandler1 和 ServiceHander2。注册 S1 不会满足,注册 S2 不会,但注册 S3 会。

    同样,您可以将 rpc proto 分解为两个服务,一个用于方法 1,一个用于方法 2,并独立处理它们。在这种情况下,您可以注册,S1 用于服务 1,S2 用于服务 2,S3 可以注册为其中任何一个。

    当请求进来时: Request --> Listener --> GRPC Server --> Multiplexed to Handler --> Spawns goroutine 来处理请求

    TLDR;只要满足服务接口,东西来自哪里都没有关系。注册甚至可以在运行时动态更改。

    【讨论】:

      【解决方案3】:

      可以说,服务器gRPCServer通过listener监听端口 80 并且可以服务于 RouteGuide、SomeOther、 SomeOtherOther 向它注册了哪些(gRPCServer)?

      是的。我无法形容得更好。

      一个服务器服务多个服务是否容易出错?

      不,完全没有问题。您最终将需要一个服务于多个服务的服务器,特别是如果您需要辅助服务(例如健康检查器、指标、缓存等)。因此,您的客户不必知道主服务中的所有方法。

      什么是 使用多台服务器时要牢记的注意事项 服务?

      (观点)我目前没有任何想法,但是您当然需要明智地选择将一起提供哪些服务,因为您不想让服务器超载或混合逻辑。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-10-06
        • 1970-01-01
        • 1970-01-01
        • 2011-11-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-21
        相关资源
        最近更新 更多