Using different proto files for server and client in gRPC - grpc

I have one proto file for gRPC server
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string othermessage = 1;
string message = 2;
string othermessage2 = 3;
}
My client don't need the fields othermessage and othermessage2. I make other proto file for client
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 2;
}
It works, but is it correct?
I see the following advantages: the client receive only the necessary data, the client's proto-file is not overloaded. For example, in sql we get only the required fields.
Maybe it's more efficient? Are all fields transmitted over the network or only the requested one?

I used the article Analyzing gRPC messages using Wireshark to validate fields sent over the network. All fields are sent. Therefore, using truncated proto files does not increase efficiency.
As a result, we can use the truncated proto file on the client, if it contains non-breaking differences, by analogy with non-breaking changes. This does not increase performance and can only be used to reduce the proto file on the client side.

Related

How to define a GRPC service method without request parameter?

Normally definde a GRPC method as follows which has a request parameter HelloRequest:
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
But how to define a method without request parameter as following SayHello method:
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello () returns (HelloReply) {}
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
Google's Well-Known Types includes Empty
Given that you must have a message for requests and responses, I think it's a good idea to define them in your protos even if initially empty unless you're absolutely confident that they'll always be empty:
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {}
message HelloReply {
string message = 1;
}

Apache Http EntityUtils.consume() vs EntityUtils.toString()?

I have written a HTTP client, where I am reading the data response from a REST web service. My confusion arises after reading multiple blogs on EntityUtils.consume() and EntiryUtils.toString(). I wanted to know the following:
If EntityUtils.toString(..) ONLY is sufficient as it also closes the stream after reading char bytes. Or I should also do EntityUtils.consume(..) as a good practice.
If both toString() and consume() operation can be used. If yes, then what should be there order.
If I EntityUtils.toString() closes the stream; then why the next call in EntityUtils.consume(..) operations which is entity.isStreaming() still returns true?
Could anyone guide me here to use these operations in a standard way. I am using HTTP version 4+.
I have to use these configurations in multithreaded(web-app) environment.
Thanks
I looked at the recommended example from the apache httpclient commons website.
In the example, they used EntityUtils.toString(..) without needing to use EntityUtils.consume(..) before or after.
They mention that calling httpclient.close() ensures all resources are closed.
source: https://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientWithResponseHandler.java
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
HttpGet httpget = new HttpGet("http://httpbin.org/");
System.out.println("Executing request " + httpget.getRequestLine());
// Create a custom response handler
ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
#Override
public String handleResponse(
final HttpResponse response) throws ClientProtocolException, IOException {
int status = response.getStatusLine().getStatusCode();
if (status >= 200 && status < 300) {
HttpEntity entity = response.getEntity();
return entity != null ? EntityUtils.toString(entity) : null;
} else {
throw new ClientProtocolException("Unexpected response status: " + status);
}
}
};
String responseBody = httpclient.execute(httpget, responseHandler);
System.out.println("----------------------------------------");
System.out.println(responseBody);
} finally {
httpclient.close();
}
This is what is quoted for the above example:
This example demonstrates how to process HTTP responses using a response handler. This is the recommended way of executing HTTP requests and processing HTTP responses. This approach enables the caller to concentrate on the process of digesting HTTP responses and to delegate the task of system resource deallocation to HttpClient. The use of an HTTP response handler guarantees that the underlying HTTP connection will be released back to the connection manager automatically in all cases.

Not getting method name or class name in native java from proto

I have created a proto file
syntax = "proto3";
package example;
message HelloRequest {
string name = 1;
}
message HelloResponse {
string greeting = 1;
}
// 4. service, unary request/response
service GreetingService {
rpc GetGreetingMethod(HelloRequest) returns (HelloResponse);
}
When I generate the code for golang I can see GetGreetingMethod method in test.pb.go (protoc --go_out=plugins=grpc:. test.proto)
But when I generate the java code ( protoc dir/test.proto --java_out=proto) I get file where I cant find my rpc function.
Same can be checked here. Any suggestion ?

does grpc service must have exactly one input parameter and one return value

let's say i have a proto file like this. can I define service like this
rpc SayHello () returns (Response) {} //service has no input
rpc SayHello (Request1,Request2) returns (Response) {}//service has two inputs
//.proto file
syntax = "proto3";
service Greeter{
rpc SayHello (Request) returns (Response) {}
}
message Request{
string request = 1;
}
message Response{
string response = 1;
}
gRPC service methods have exactly one input message and exactly one output message. Typically, these messages are used as input and output to only one method. This is on purpose, as it allows easily adding new parameters later (to the messages) while maintaining backward compatibility.
If you don't want any input or output parameters, you can use the well-known proto google.protobuf.Empty. However, this is discouraged as it prevents you from adding parameters to the method in the future. Instead, you would be encouraged to follow the normal practice of having a message for the request, but simply with no contents:
service Greeter {
rpc SayHello (SayHelloRequest) returns (SayHelloResponse) {}
}
message SayHelloRequest {} // service has no input
Similarly, if you want two request parameters, just include both in the request message:
message SayHelloRequest { // service has two inputs
string request = 1;
string anotherRequestParam = 2;
}

GRPC: Client ID or connection information?

Is there a way to get the connection information on RPC calls from server side? Or maybe something like unique client ID?
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.
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)
....
....
}
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.
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.
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)
}
}

Resources