【问题标题】:Sending GRPC communications over a specific port通过特定端口发送 GRPC 通信
【发布时间】:2019-07-30 19:28:57
【问题描述】:

我正在运行一个在特定端口上侦听的 GRPC 服务器(服务器 A)。我希望能够向另一台服务器(服务器 B)发送通信,并让服务器 B 记录服务器 A 连接的传入地址,以便稍后与服务器 A 联系。

在服务器 A 上,我监听一个端口并创建如下上下文:

lis, err := net.Listen("tcp", "0.0.0.0:6000")
ctx, cancel := context.WithTimeout(context.Background(),
    10000*time.Millisecond)

然后像这样创建一个连接:

connection, err = grpc.DialContext(ctx, server2Address,
grpc.WithInsecure(), grpc.WithBlock())

在最终向服务器 B 上的端点发送消息之前,该端点尝试读取服务器 A 的传入连接的 IP 地址

info, _ := peer.FromContext(ctx)
fmt.Printf(info.Addr.String()) // Returns a random port, NOT 6000,

但是,服务器 B 打印的结果端口是随机的,例如 62056,而不是预期的 6000。我的假设是,在服务器 A 上,GRPC 从随机端口拨号 - 是否可以强制 GRPC 从端口 6000 而不是随机端口拨号?

【问题讨论】:

  • 为什么要关心客户端的端口号?您想在这里解决的更大的问题是什么?
  • 服务器 A 知道服务器 B 的地址和端口,但不知道相反。不知何故,我需要通知服务器 B 服务器 A 的地址和端口,以便服务器 B 将来可以与服务器 A 通信。因此,我试图从服务器 A 的传入通信提供的上下文中抓取该信息到但是,服务器 B 的端口号不准确,因此发了这篇文章。
  • 为什么不在 serverA 上的已知端口上托管 gRPC 服务,以便服务器 B 可以直接回话?您是否尝试这样做以处理特定事务并需要维护事务状态?如果是这样,我会使用一些令牌交换而不是涉及一些可能复杂的通信路径。

标签: go grpc


【解决方案1】:

您可以像这样指定源端口:

cc, err := grpc.Dial("127.0.0.1:6001", grpc.WithInsecure(),
    grpc.WithContextDialer(func(ctx context.Context, addr string) (net.Conn, error) {
        dst, err := net.ResolveTCPAddr("tcp", addr)
        if err != nil {
            return nil, err
        }
        src := &net.TCPAddr{
            IP:   net.ParseIP("127.0.0.1"),
            Port: 6000,
        }
        return net.DialTCP("tcp", src, dst)
    }))

但是,如果您的服务器正在侦听同一端口,这将导致错误:

panic: dial tcp 127.0.0.1:6000->127.0.0.1:6001: bind: address already in use

另一种方法是将地址作为元数据传递。在你做的客户端上:

ctx := context.Background()
ctx = metadata.NewOutgoingContext(ctx, metadata.Pairs("address", "127.0.0.1:6000"))
res, err := grpc_health_v1.NewHealthClient(cc).Check(ctx, &grpc_health_v1.HealthCheckRequest{
    Service: "test",
})

在服务器上:

func (s *server) Check(ctx context.Context, req *grpc_health_v1.HealthCheckRequest) (*grpc_health_v1.HealthCheckResponse, error) {
    if md, ok := metadata.FromIncomingContext(ctx); ok {
        addr := md.Get("address")
        // addr == "127.0.0.1:6000"
    }

    return &grpc_health_v1.HealthCheckResponse{
        Status: grpc_health_v1.HealthCheckResponse_SERVING,
    }, nil
}

第三种方法是使用streaming

【讨论】:

  • 你好,太好了!但是...如何在 java-client 通道上指定源端口 = ManagedChannelBuilder.forAddress(host, port).build();
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多