• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc.examples.waitforready;
18 
19 import io.grpc.Channel;
20 import io.grpc.Deadline;
21 import io.grpc.Grpc;
22 import io.grpc.InsecureChannelCredentials;
23 import io.grpc.ManagedChannel;
24 import io.grpc.StatusRuntimeException;
25 import io.grpc.examples.helloworld.GreeterGrpc;
26 import io.grpc.examples.helloworld.HelloRequest;
27 import io.grpc.examples.helloworld.HelloReply;
28 import java.util.concurrent.TimeUnit;
29 import java.util.logging.Level;
30 import java.util.logging.Logger;
31 
32 /**
33  * This is an example of using waitForReady.  This is a feature which can be used on a stub
34  * which will cause the rpcs to wait (until optional deadline is exceeded) for the
35  * server to become available before sending the request.  This is useful for batch workflows
36  * where there is no need to fail fast.
37  *
38  * Below is a simple client that requests a greeting from the
39  * {@link io.grpc.examples.helloworld.HelloWorldServer} and defines waitForReady on the stub.
40  * To test,
41  *   1. run this client without a server running - client rpc should hang
42  *   2. start the server - client rpc should complete
43  *   3. run this client again - client rpc should complete nearly immediately
44  */
45 public class WaitForReadyClient {
46   private static final Logger logger = Logger.getLogger(WaitForReadyClient.class.getName());
47 
48   private final GreeterGrpc.GreeterBlockingStub blockingStub;
49 
50   /**
51    *  Construct client for accessing HelloWorld server using the existing channel which will
52    *  wait for the server to become ready, however long that may take, before sending the request.
53    */
WaitForReadyClient(Channel channel)54   public WaitForReadyClient(Channel channel) {
55     // This is the only difference from the simple HelloWorld example
56     blockingStub = GreeterGrpc.newBlockingStub(channel).withWaitForReady();
57   }
58 
59   /**
60    *  Construct a client for accessing HelloWorld server using the existing channel which will
61    *  wait for the server to become ready, up to the specified deadline, before sending the request.
62    *  if the deadline is exceeded before the server becomes ready, then the rpc call will fail with
63    *  a Status of DEADLINE_EXCEEDED without the request being sent.
64    */
WaitForReadyClient(Channel channel, Deadline deadline)65   public WaitForReadyClient(Channel channel, Deadline deadline) {
66     blockingStub = GreeterGrpc.newBlockingStub(channel).withWaitForReady().withDeadline(deadline);
67   }
68 
69 
70   /** Say hello to server. */
greet(String name)71   public void greet(String name) {
72     logger.info("Will try to greet " + name + " ...");
73     HelloRequest request = HelloRequest.newBuilder().setName(name).build();
74     HelloReply response;
75     try {
76       response = blockingStub.sayHello(request);
77     } catch (StatusRuntimeException e) {
78       logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
79       return;
80     }
81     logger.info("Greeting: " + response.getMessage());
82   }
83 
84   /**
85    * Greet server. If provided, the first element of {@code args} is the name to use in the
86    * greeting. The second argument is the target server.
87    */
main(String[] args)88   public static void main(String[] args) throws Exception {
89     String user = "world";
90     // Access a service running on the local machine on port 50051
91     String target = "localhost:50051";
92     // Allow passing in the user and target strings as command line arguments
93     if (args.length > 0) {
94       if ("--help".equals(args[0])) {
95         System.err.println("Usage: [name [target]]");
96         System.err.println();
97         System.err.println("  name    The name you wish to be greeted by. Defaults to " + user);
98         System.err.println("  target  The server to connect to. Defaults to " + target);
99         System.exit(1);
100       }
101       user = args[0];
102     }
103     if (args.length > 1) {
104       target = args[1];
105     }
106 
107     // Create a communication channel to the server, known as a Channel. Channels are thread-safe
108     // and reusable. It is common to create channels at the beginning of your application and reuse
109     // them until the application shuts down.
110     //
111     // For the example we use plaintext insecure credentials to avoid needing TLS certificates. To
112     // use TLS, use TlsChannelCredentials instead.
113     ManagedChannel channel = Grpc.newChannelBuilder(target, InsecureChannelCredentials.create())
114         .build();
115     try {
116       // If server isn't running, this will fail after 5 seconds.  Will also fail if the server is
117       // running particularly slowly and takes more than 5 minutes to respond.
118       WaitForReadyClient clientWithTimeout =
119           new WaitForReadyClient(channel, Deadline.after(5, TimeUnit.SECONDS));
120       clientWithTimeout.greet(user);
121 
122       // This will wait forever until the server becomes ready
123       WaitForReadyClient client = new WaitForReadyClient(channel);
124       client.greet(user);
125     } finally {
126       // ManagedChannels use resources like threads and TCP connections. To prevent leaking these
127       // resources the channel should be shut down when it will no longer be used. If it may be used
128       // again leave it running.
129       channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
130     }
131   }
132 }
133