问题
In this tutorial and example code, a server can call onNext()
method on every stream observer, which will broadcast messages to all clients bi-streaming with the server. But there is no method to identify which observer corresponds to which client. How can a server push a message to specific client instead of broadcasting?
According to this answer it is possible to map each observer if client id is provided by metadata. It seems const auto clientMetadata = context->client_metadata();
part does the trick, but I'm working with Java, not C++. Are there any Java equivalent for getting the metadata at server side?
回答1:
The answer depends a bit on how the clients will be identified. If the initial request provided a handle (like a username, but not registered ahead-of-time), then you could just wait for the first onNext()
:
public StreamObserver<Chat.ChatMessage> chat(StreamObserver<Chat.ChatMessageFromServer> responseObserver) {
return new StreamObserver<Chat.ChatMessage>() {
@Override
public void onNext(Chat.ChatMessage value) {
String userHandle = value.getHandle();
// observers would now be a map, not a set
observers.put(userHandle, responseObserver);
...
Let's say instead that all users are logged in, and provide a token in the headers, like OAuth. Then you would use an interceptor to authenticate the user and Context to propagate it to the application, as in https://stackoverflow.com/a/40113309/4690866 .
public StreamObserver<Chat.ChatMessage> chat(StreamObserver<Chat.ChatMessageFromServer> responseObserver) {
// USER_IDENTITY is a Context.Key, also used by the interceptor
User user = USER_IDENTITY.get();
observers.put(user.getName(), responseObserver);
return new StreamObserver<Chat.ChatMessage>() {
...
The first one is easier/nicer when the identification only applies to this one RPC. The second one is easier/nicer when the identification applies to many RPCs.
来源:https://stackoverflow.com/questions/55394150/grpc-how-can-i-distinguish-bi-streaming-clients-at-server-side