GRPC: Client ID or connection information?
Asked Answered
U

4

13

Is there a way to get the connection information on RPC calls from server side? Or maybe something like unique client ID?

Unrefined answered 11/1, 2017 at 5:19 Comment(5)
Depending on the programming language with which you are working this might be possible today or "coming soon". With what programming language(s) are you working with gRPC?Caruncle
I'm using C++ and Rust (unofficial Rust port github.com/stepancheg/grpc-rust , I don't think they support it yet)Unrefined
What do you want to achieve? Designs using a client ID are typically broken.Lucifer
It's a game api, and say, if client1 calls Jump() then server should know which player in the game should jump.Unrefined
@KibeomKim man were you able to find a solution to distinguish clients ?Galenical
S
8

There is no connecton information which may help distinguish clients. One reason of this is proxies: different clients can have same IP and port (as I understand)

One possible solution is handshake protocol in app level. You can add rpc method "Connect" and send clientId as response from server. Afterthat you can attach custom headers (metadata) to your rpc calls.

Client side java code:

String clientId = getIdfromServer();
Metadata.Key<String> CLIENT_ID = Metadata.Key.of("client_id", ASCII_STRING_MARSHALLER);
Metadata fixedHeaders = new Metadata();
fixedHeaders.put(CLIENT_ID, clientId);
blockingStub = MetadataUtils.attachHeaders(blockingStub, fixedHeaders);

This C++ server side code shows how to handle such header on server:

::grpc::Status YourRPC(::grpc::ServerContext* context, const Your* request, YourResponse* response)
{
    const auto clientMetadata = context->client_metadata();
    auto it = clientMetadata.find("client_id");
    auto clientId = std::string(it->second.begin(), it->second.end());
}

I noticed that metadata key is case insensitive. Grpc converts keys to lowercase.

Springtail answered 12/4, 2017 at 3:5 Comment(0)
P
3

gRPC now provide peer information (https://github.com/grpc/grpc-go/issues/334)

import ( "google.golang.org/grpc/peer" )

func (s *server) Hello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
  //p includes connection information
  p, ok := peer.FromContext(ctx)
  ....
  ....
}
Pavis answered 27/11, 2018 at 7:48 Comment(0)
G
2

Yes , we can get the request information , connection information and etc. There are generally two types of information we can get from the client request on grpc server side.

  1. Method Information : We know that rpc call is simple method call . To get the method name (ie : which method will be invoked in grpc server when client will request?). below code will work.

      import (
       "google.golang.org/grpc"
      )
    
      func getMethodInfo(ctx context.Context) {
         methodName := grpc.Method(ctx)
         fmt.Println(methodName)
        }
     //outputex: /Abc
    

2.Peer Information:

    p, ok := peer.FromContext(ctx)

Hope this will work.

Glamorize answered 29/4, 2021 at 6:51 Comment(0)
S
1

For gRPC streaming

We can get the connection information below through google.golang.org/grpc/peer

// protobuf
service Server {
  rpc Stream (stream GrpcStreamRequest) returns (stream GrpcStreamResponse) {}
}

func (ss *StreamServer) Stream(svr pb.Server_StreamServer) error {
    for {
        req, err := svr.Recv()
        if err != nil {
            fmt.Printf("Stream recv err %+v", err)
            return err
        }
        p, ok := peer.FromContext(svr.Context())
        if ok {
            fmt.Printf("Client info %+v", p)
        }
}
Sevilla answered 22/4, 2022 at 4:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.