How to Know If a Grpc Server Is Available

How to know if a GRPC server is available

Take a look at ChannelConnectivity - I am a go programmer but it should be the same in python. What I do is create while/for loop and when the "ChannelConnectivity" is set to "READY" I create the client from the connection and then continue.

Golang grpc: how to determine when the server has started listening?

s.Serve(listener) blocks, so you can't achieve your purpose by having a done chan, instead you have to implement the healthcheck and readiness for your service, and check those before performing any request by the client.
The server should implement the following proto:

syntax = "proto3";

package grpc.health.v1;

message HealthCheckRequest {
string service = 1;
}

message HealthCheckResponse {
enum ServingStatus {
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
SERVICE_UNKNOWN = 3; // Used only by the Watch method.
}
ServingStatus status = 1;
}

service Health {
rpc Check(HealthCheckRequest) returns (HealthCheckResponse);

rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);
}

For example, the envoy proxy grpc_health_check works with the above proto.

Read GRPC Health Checking Protocol for more information.

Ways to wait if server is not available in gRPC from client side

When you call grpc.Dial to connect to a server and receive a grpc.ClientConn, it will automatically handle reconnections for you. When you call a method or request a stream, it will fail if it can't connect to the server or if there is an error processing the request.

You could retry a few times if the error indicates that it is due to the network. You can check the grpc status codes in here https://github.com/grpc/grpc-go/blob/master/codes/codes.go#L31 and extract them from the returned error using status.FromError: https://pkg.go.dev/google.golang.org/grpc/status#FromError

You also have the grpc.WaitForReady option (https://pkg.go.dev/google.golang.org/grpc#WaitForReady) which can be used to block the grpc call until the server is ready if it is in a transient failure. In that case, you don't need to retry, but you should probably add a timeout that cancels the context to have control over how long you stay blocked.

If you want to even avoid trying to call the server, you could use ClientConn.WaitForStateChange (which is experimental) to detect any state change and call ClientConn.GetState to determine in what state is the connection to know when it is safe to start calling the server again.

gRPC (cpp) - How can I check if the RPC channel connected successfully?

Before I directly answer your question, let me provide some background.

A gRPC channel is not actually the same as a connection. In fact, a channel may have more than one underlying connection active in parallel, depending on what load balancing policy the channel is using. The intent of the channel API is that it abstracts away the details of individual connections from the application; the idea is that the application should think of a channel as a generic interface on which RPCs are sent, and the channel will internally handle the details of connection management automatically, so the application doesn't have to worry about them.

So at a high level, I think that your application should not need to know or care whether the channel is connected. If you think it does need to know that, then I would actually consider that an indication that you need to step back and rethink how you are architecting the application.

In particular, I'm not sure exactly what you mean by "I don't want to make any of the RPC calls that we defined, as they all have effects that will occur", but that sounds a little strange to me. I assume that you mean that there could be effects on the server's state, which implies that the RPC is not idempotent. You may want to consider changing it to be idempotent somehow, since that is safer (I'll come back to why in a minute). But even if you are dealing with a non-idempotent RPC, I don't see how knowing the state of the underlying connection would help you avoid that problem. Even if the channel was connected at the moment the client initiates the RPC, there is never a guarantee that the server will see it, because the connection could fail right after the application tells gRPC to send it but before it goes out on the wire. Or the network itself could fail to deliver it to the server after gRPC puts it on the wire. Or, worse, the server could see it but the network could fail before the server's response gets back to the client. There's really no guarantee that an RPC will be atomic, nor is there any guarantee that the client and server will have the same view of whether or not the RPC succeeded. All the client knows in any of these cases is that the RPC failed, but it cannot infer from that whether or not the server actually saw the RPC.

This is why designing your RPCs to be idempotent generally makes more sense. Instead of focusing on whether or not the channel is connecteed, you can focus on whether or not individual RPCs succeed. Any time the client sees that an RPC has failed, it can retry it. And if the server happens to see the same RPC twice, that won't break things (e.g., if you replay a delete operation, it will notice that the data has already been deleted, so it will be a no-op).

So, my high-level answer is, your client code should react to individual RPC failures, not to connection failures.

All of that having been said, if you do actually want to monitor the channel's connectivity state, you can do so using the connectivity state API. Note that a gRPC channel does not actually initiate a connection immediately when you create it. Initially, it is in state IDLE. It will attempt to connect (and transition to state CONNECTING) when either (a) you send the first RPC on the channel or (b) you call channel->GetState(true) to explicitly ask it to connect. If the connection attempt fails, the channel will transition to state TRANSIENT_FAILURE, and it will retry periodically. When it has established a connection, it will transition to state READY.

Any RPC sent on a channel in state TRANSIENT_FAILURE will fail immediately, unless it is wait_for_ready. The same is true for an RPC that is still pending when the channel transitions into state TRANSIENT_FAILURE (e.g., if the channel was initially in state IDLE and started to connect as a result of the RPC being sent, but then the initial connection attempt failed).

With regard to lame channels, note that that only happens in the rare case where you try to create a channel using a malformed target URI that gRPC does not know how to parse. If gRPC knows that it will never be able to resolve the name you specified, it will return a lame channel, which is basically a channel that is permanently in state TRANSIENT_FAILURE.

I hope this information is helpful.



Related Topics



Leave a reply



Submit