简体   繁体   English

gRPC:如何在 stream gRPC 中找到特定的客户端

[英]gRPC : How to find a specific client in the stream gRPC

I want to create Client and Server through gRPC Server Streaming.我想通过 gRPC Server Streaming 创建客户端和服务器。 I would like to distinguish each client at this time.我想在这个时候区分每个客户。 I looked into it, and I think we can choose using Uid to distinguish client or use peer to distinguish it.我查了一下,我觉得可以选择用Uid来区分client或者用peer来区分。

What I am curious about is that when I want to send a response to only one specific client, I wonder if there is only a way to distinguish it through uid or peer after sending it to everyone.我比较好奇的是,当我只想给一个特定的client发送response的时候,想知道是不是只有发给所有人之后,通过uid或者peer来区分。 Can't the server send it to only one client from the beginning?服务器不能从一开始就只发送给一个客户端吗?

For example, suppose you created a server streaming grpc service called send(), request send() from multiple clients and wait for a response through stream. The server needs to respond to send() to a particular client, but I don't know how to generate only the send() service for this particular client.例如,假设你创建了一个名为 send() 的服务器流式 grpc 服务,从多个客户端请求 send() 并等待通过 stream 的响应。服务器需要响应 send() 到特定的客户端,但我没有知道如何只为这个特定的客户端生成 send() 服务。

One solution (but there might be better solutions) could be to pass a unique ID from the client to the server in the metadata, and have a centralized storage, like a singleton client manager class, for all connected clients on the server-side.一种解决方案(但可能有更好的解决方案)可能是在元数据中将唯一 ID 从客户端传递到服务器,并为服务器端所有连接的客户端提供集中存储,如 singleton客户端管理器class。 This client manager class decides to who streams happen, and to who not.这位客户经理 class 决定对谁进行流式传输,对谁不进行流式传输。

For example, on the client-side the machine name is passed in the metadata when subscribing to the server stream as a identifier with the key client-id (though something like a GUID would probably more unique):例如,在客户端,当订阅服务器 stream 时,机器名称作为带有密钥client-id的标识符在元数据中传递(尽管像 GUID 这样的东西可能更独特):

// client-side method that subscribes to the gRPC client
public async void Subscribe()
{
    // subscribe to the server stream with a unique client id
    _call = _serviceClient.SubscribeToServerStream(new Empty(), headers: new Metadata
    {
        new Metadata.Entry("client-id", Environment.MachineName)
    });

    // handle incoming messages from the server for this client
    await HandleIncomingServerMessages(_call.ResponseStream);
}

The server-side code is kinda simplified, but I think it explains the idea.服务器端代码有点简化,但我认为它解释了这个想法。 The client-id gets extracted from the metadata, and added to the (singleton) _clientManager class, which holds all connected clients and manages to who streams should happen. client-id从元数据中提取,并添加到(单例) _clientManager class,它保存所有连接的客户端并管理应该发生的流。 Now if you want to stream to this connected client, the centralized client manager can set (just as an example) this client's streaming property to active, and you can check in the outgoing stream if this client is active or not (with the id you extracted from the call context), and therefore stream messages or not.现在如果你想 stream 到这个连接的客户端,集中式客户端管理器可以设置(作为一个例子)这个客户端的流媒体属性为活动的,你可以检查传出的 stream 这个客户端是否是活动的(使用你的 ID从调用上下文中提取),因此是否有 stream 条消息。

// server-side method in the gRPC service that implements the stream
public override async Task SubscribeToServerStream(Empty request,
    IServerStreamWriter<Message> responseStream,
    ServerCallContext context)
{
    // extract the unique client id
    _clientId = context.RequestHeaders.FirstOrDefault(m => String.Equals(m.Key, "client-id", StringComparison.Ordinal));

    // register it to the server-side client manager
    _clientManager.AddNewConnectedClient(_clientId);

    while(_isStreaming)
    {
        if(_clientManager.IsActiveClient(this._clientId))
        {
            // this client is set to active in the manager, therefore stream
        }
        else
        {
            // do nothing, since you currently do not want to stream to this connected client
        }
    }
}

I am pretty sure this will work, since I implemented something very similar not long ago, although it was kinda hacky (where multiple clients could connect, but only one of them could receive a stream at the same time, and there were some other conditions).我很确定这会奏效,因为我不久前实现了非常相似的东西,虽然它有点 hacky(多个客户端可以连接,但其中只有一个可以同时收到 stream,还有一些其他条件). But there might be better solutions to your problem than my answer, and I sadly do not have the time to write down and debug all the code to give you something that works out of the box.但是对于你的问题可能有比我的答案更好的解决方案,遗憾的是我没有时间写下和调试所有代码来给你一些开箱即用的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM