• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 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.helloworldxds;
18 
19 import io.grpc.InsecureServerCredentials;
20 import io.grpc.Server;
21 import io.grpc.ServerCredentials;
22 import io.grpc.health.v1.HealthCheckResponse.ServingStatus;
23 import io.grpc.protobuf.services.ProtoReflectionService;
24 import io.grpc.services.HealthStatusManager;
25 import io.grpc.xds.XdsServerBuilder;
26 import io.grpc.xds.XdsServerCredentials;
27 import java.util.Arrays;
28 import java.io.IOException;
29 import java.util.concurrent.TimeUnit;
30 
31 /**
32  * An xDS-managed Server for the {@code Greeter} service.
33  */
34 public class XdsHelloWorldServer {
main(String[] args)35   public static void main(String[] args) throws IOException, InterruptedException {
36     int port = 50051;
37     String hostname = null;
38     ServerCredentials credentials = InsecureServerCredentials.create();
39     if (args.length >= 1 && "--xds-creds".equals(args[0])) {
40       // The xDS credentials use the security configured by the xDS server when available. When xDS
41       // is not used or when xDS does not provide security configuration, the xDS credentials fall
42       // back to other credentials (in this case, InsecureServerCredentials).
43       credentials = XdsServerCredentials.create(InsecureServerCredentials.create());
44       args = Arrays.copyOfRange(args, 1, args.length);
45     }
46     if (args.length >= 1) {
47       try {
48         port = Integer.parseInt(args[0]);
49       } catch (NumberFormatException ex) {
50         System.err.println("Usage: [--xds-creds] [PORT [HOSTNAME]]");
51         System.err.println("");
52         System.err.println("  --xds-creds  Use credentials provided by xDS. Defaults to insecure");
53         System.err.println("");
54         System.err.println("  PORT      The listen port. Defaults to " + port);
55         System.err.println("  HOSTNAME  The name clients will see in greet responses. ");
56         System.err.println("            Defaults to the machine's hostname");
57         System.exit(1);
58       }
59     }
60     if (args.length >= 2) {
61       hostname = args[1];
62     }
63     // Since the main server may be using TLS, we start a second server just for plaintext health
64     // checks
65     int healthPort = port + 1;
66     final HealthStatusManager health = new HealthStatusManager();
67     final Server server = XdsServerBuilder.forPort(port, credentials)
68         .addService(new HostnameGreeter(hostname))
69         .addService(ProtoReflectionService.newInstance()) // convenient for command line tools
70         .addService(health.getHealthService()) // allow management servers to monitor health
71         .build()
72         .start();
73     final Server healthServer =
74         XdsServerBuilder.forPort(healthPort, InsecureServerCredentials.create())
75         .addService(health.getHealthService()) // allow management servers to monitor health
76         .build()
77         .start();
78     System.out.println("Listening on port " + port);
79     System.out.println("Plaintext health service listening on port " + healthPort);
80     Runtime.getRuntime().addShutdownHook(new Thread() {
81       @Override
82       public void run() {
83         health.setStatus("", ServingStatus.NOT_SERVING);
84         // Start graceful shutdown
85         server.shutdown();
86         try {
87           // Wait for RPCs to complete processing
88           if (!server.awaitTermination(30, TimeUnit.SECONDS)) {
89             // That was plenty of time. Let's cancel the remaining RPCs
90             server.shutdownNow();
91             // shutdownNow isn't instantaneous, so give a bit of time to clean resources up
92             // gracefully. Normally this will be well under a second.
93             server.awaitTermination(5, TimeUnit.SECONDS);
94           }
95           healthServer.shutdownNow();
96           healthServer.awaitTermination(5, TimeUnit.SECONDS);
97         } catch (InterruptedException ex) {
98           server.shutdownNow();
99           healthServer.shutdownNow();
100         }
101       }
102     });
103     // This would normally be tied to the service's dependencies. For example, if HostnameGreeter
104     // used a Channel to contact a required service, then when 'channel.getState() ==
105     // TRANSIENT_FAILURE' we'd want to set NOT_SERVING. But HostnameGreeter has no dependencies, so
106     // hard-coding SERVING is appropriate.
107     health.setStatus("", ServingStatus.SERVING);
108     server.awaitTermination();
109   }
110 }
111