mirror of https://github.com/grpc/grpc-java.git
xds: create a full xDS example with XDS Channel creds and server xDS options (#7535)
This commit is contained in:
parent
26a4ca38ec
commit
b6601ba273
|
|
@ -1,9 +1,9 @@
|
||||||
gRPC XDS Example
|
gRPC XDS Example
|
||||||
================
|
================
|
||||||
|
|
||||||
The XDS example is a Hello World client capable of being configured with the
|
The XDS example consists of a Hello World client and a Hello World server capable of
|
||||||
XDS management protocol. Out-of-the-box it behaves the same as hello world
|
being configured with the XDS management protocol. Out-of-the-box they behave the same
|
||||||
client.
|
as their hello-world version.
|
||||||
|
|
||||||
__XDS support is incomplete and experimental, with limited compatibility. It
|
__XDS support is incomplete and experimental, with limited compatibility. It
|
||||||
will be very hard to produce a working enviornment just by this example. Please
|
will be very hard to produce a working enviornment just by this example. Please
|
||||||
|
|
@ -12,40 +12,60 @@ environment.__
|
||||||
|
|
||||||
### Build the example
|
### Build the example
|
||||||
|
|
||||||
1. Build the hello-world example server or the hostname example server. See
|
Build the XDS hello-world example client & server. From the `grpc-java/examples/examples-xds`
|
||||||
[the examples README](../README.md) or the
|
directory:
|
||||||
[hostname example README](../example-hostname/README.md).
|
|
||||||
|
|
||||||
2. Build the xds hello-world example client. From the `grpc-java/examples/examples-xds` directory:
|
|
||||||
```
|
```
|
||||||
$ ../gradlew installDist
|
$ ../gradlew installDist
|
||||||
```
|
```
|
||||||
|
|
||||||
This creates the script `build/install/example-xds/bin/xds-hello-world-client`
|
This creates the scripts `build/install/example-xds/bin/hello-world-client-xds` and
|
||||||
that runs the example.
|
`build/install/example-xds/bin/hello-world-server-xds`.
|
||||||
|
|
||||||
To start the server, run:
|
### Run the example without using XDS Credentials
|
||||||
|
|
||||||
```
|
To use XDS, you should first deploy the XDS management server in your deployment environment
|
||||||
$ ../build/install/hostname/bin/hello-world-server
|
and know its name. You need to set the `GRPC_XDS_BOOTSTRAP` environment variable to point to the
|
||||||
$ # or
|
gRPC XDS bootstrap file (see
|
||||||
$ ../example-hostname/build/install/hostname/bin/hostname-server
|
[gRFC A27](https://github.com/grpc/proposal/blob/master/A27-xds-global-load-balancing.md#xdsclient-and-bootstrap-file) for the
|
||||||
```
|
bootstrap format). This is needed by both `build/install/example-xds/bin/hello-world-client-xds`
|
||||||
|
and `build/install/example-xds/bin/hello-world-server-xds`.
|
||||||
And in a different terminal window run this client:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ ./build/install/example-xds/bin/xds-hello-world-client
|
|
||||||
```
|
|
||||||
|
|
||||||
However, that didn't use XDS! To use XDS we assume you have deployed the server
|
|
||||||
in your deployment environment and know its name. You need to set the
|
|
||||||
`GRPC_XDS_BOOTSTRAP` environment variable to point to a gRPC XDS bootstrap
|
|
||||||
file (see [gRFC A27](https://github.com/grpc/proposal/pull/170) for the
|
|
||||||
bootstrap format). Then use the `xds:` target scheme during
|
|
||||||
channel creation.
|
|
||||||
|
|
||||||
|
1. To start the XDS-enabled example server, run:
|
||||||
```
|
```
|
||||||
$ export GRPC_XDS_BOOTSTRAP=/path/to/bootstrap.json
|
$ export GRPC_XDS_BOOTSTRAP=/path/to/bootstrap.json
|
||||||
$ ./build/install/example-xds/bin/xds-hello-world-client "XDS world" xds:///yourServersName
|
$ ./build/install/example-xds/bin/hello-world-server-xds 8000 my-test-xds-server
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The first command line argument is the port to listen on (`8000`) and the second argument is a string
|
||||||
|
id (`my-test-xds-server`) to be included in the greeting response to the client.
|
||||||
|
|
||||||
|
2. In a different terminal window, run the XDS-enabled example client:
|
||||||
|
```
|
||||||
|
$ export GRPC_XDS_BOOTSTRAP=/path/to/bootstrap.json
|
||||||
|
$ ./build/install/example-xds/bin/xds-hello-world-client xds:///yourServersName:8000 my-test-xds-client
|
||||||
|
```
|
||||||
|
The first command line argument (`xds:///yourServersName:8000`) is the target to connect to using the
|
||||||
|
`xds:` target scheme and the second argument (`my-test-xds-client`) is the name you wish to include in
|
||||||
|
the greeting request to the server.
|
||||||
|
|
||||||
|
### Run the example with xDS Credentials
|
||||||
|
|
||||||
|
The above example used plaintext (insecure) credentials as explicitly provided by the client and server
|
||||||
|
code. We will now demonstrate how the code can authorize use of xDS provided credentials by using
|
||||||
|
`XdsChannelCredentials` on the client side and using `XdsServerBuilder.useXdsSecurityWithPlaintextFallback()`
|
||||||
|
on the server side. This code is enabled by providing an additional command line argument.
|
||||||
|
|
||||||
|
1. On the server side, add `--secure` on the command line to authorize use of xDS security:
|
||||||
|
```
|
||||||
|
$ export GRPC_XDS_BOOTSTRAP=/path/to/bootstrap.json
|
||||||
|
$ ./build/install/example-xds/bin/hello-world-server-xds 8000 my-test-xds-server --secure
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Similarly, add `--secure` on the comamnd line when you run the xDS client:
|
||||||
|
```
|
||||||
|
$ export GRPC_XDS_BOOTSTRAP=/path/to/bootstrap.json
|
||||||
|
$ ./build/install/example-xds/bin/hello-world-client-xds xds:///yourServersName:8000 my-test-xds-client --secure
|
||||||
|
```
|
||||||
|
|
||||||
|
In this case, if the xDS management server is configured to provide mTLS credentials (for example) to the client and
|
||||||
|
server, then they will use these credentials to create an mTLS channel to authenticate and encrypt.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
plugins {
|
plugins {
|
||||||
id 'application' // Provide convenience executables for trying out the examples.
|
id 'application' // Provide convenience executables for trying out the examples.
|
||||||
|
// ASSUMES GRADLE 5.6 OR HIGHER. Use plugin version 0.8.10 with earlier gradle versions
|
||||||
|
id 'com.google.protobuf' version '0.8.13'
|
||||||
|
// Generate IntelliJ IDEA's .idea & .iml project files
|
||||||
|
id 'idea'
|
||||||
id 'java'
|
id 'java'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -19,25 +23,46 @@ targetCompatibility = 1.7
|
||||||
// Feel free to delete the comment at the next line. It is just for safely
|
// Feel free to delete the comment at the next line. It is just for safely
|
||||||
// updating the version in our release process.
|
// updating the version in our release process.
|
||||||
def grpcVersion = '1.34.0-SNAPSHOT' // CURRENT_GRPC_VERSION
|
def grpcVersion = '1.34.0-SNAPSHOT' // CURRENT_GRPC_VERSION
|
||||||
|
def nettyTcNativeVersion = '2.0.31.Final'
|
||||||
|
def protocVersion = '3.12.0'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// This example's client is the same as the helloworld client. We depend on the helloworld
|
implementation "io.grpc:grpc-netty:${grpcVersion}"
|
||||||
// client's code here
|
implementation "io.grpc:grpc-protobuf:${grpcVersion}"
|
||||||
implementation ':examples'
|
implementation "io.grpc:grpc-stub:${grpcVersion}"
|
||||||
// The only change necessary is an extra runtime dependency on io.grpc:grpc-xds
|
implementation "io.grpc:grpc-xds:${grpcVersion}"
|
||||||
runtimeOnly "io.grpc:grpc-xds:${grpcVersion}"
|
compileOnly "org.apache.tomcat:annotations-api:6.0.53"
|
||||||
|
runtimeOnly "io.netty:netty-tcnative-boringssl-static:${nettyTcNativeVersion}"
|
||||||
|
}
|
||||||
|
|
||||||
|
protobuf {
|
||||||
|
protoc { artifact = "com.google.protobuf:protoc:${protocVersion}" }
|
||||||
|
plugins {
|
||||||
|
grpc { artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" }
|
||||||
|
}
|
||||||
|
generateProtoTasks {
|
||||||
|
all()*.plugins { grpc {} }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startScripts.enabled = false
|
startScripts.enabled = false
|
||||||
|
|
||||||
task helloWorldClient(type: CreateStartScripts) {
|
task helloWorldClientXds(type: CreateStartScripts) {
|
||||||
mainClassName = 'io.grpc.examples.helloworld.HelloWorldClient'
|
mainClassName = 'io.grpc.examples.helloworldxds.HelloWorldClientXds'
|
||||||
applicationName = 'xds-hello-world-client'
|
applicationName = 'hello-world-client-xds'
|
||||||
|
outputDir = new File(project.buildDir, 'tmp')
|
||||||
|
classpath = startScripts.classpath
|
||||||
|
}
|
||||||
|
|
||||||
|
task helloWorldServerXds(type: CreateStartScripts) {
|
||||||
|
mainClassName = 'io.grpc.examples.helloworldxds.HelloWorldServerXds'
|
||||||
|
applicationName = 'hello-world-server-xds'
|
||||||
outputDir = new File(project.buildDir, 'tmp')
|
outputDir = new File(project.buildDir, 'tmp')
|
||||||
classpath = startScripts.classpath
|
classpath = startScripts.classpath
|
||||||
}
|
}
|
||||||
|
|
||||||
applicationDistribution.into('bin') {
|
applicationDistribution.into('bin') {
|
||||||
from(helloWorldClient)
|
from(helloWorldClientXds)
|
||||||
|
from(helloWorldServerXds)
|
||||||
fileMode = 0755
|
fileMode = 0755
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 The gRPC Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.grpc.examples.helloworldxds;
|
||||||
|
|
||||||
|
import io.grpc.ChannelCredentials;
|
||||||
|
import io.grpc.Grpc;
|
||||||
|
import io.grpc.InsecureChannelCredentials;
|
||||||
|
import io.grpc.ManagedChannel;
|
||||||
|
import io.grpc.ManagedChannelBuilder;
|
||||||
|
import io.grpc.StatusRuntimeException;
|
||||||
|
import io.grpc.examples.helloworld.GreeterGrpc;
|
||||||
|
import io.grpc.examples.helloworld.HelloReply;
|
||||||
|
import io.grpc.examples.helloworld.HelloRequest;
|
||||||
|
import io.grpc.netty.GrpcSslContexts;
|
||||||
|
import io.grpc.netty.NettyChannelBuilder;
|
||||||
|
import io.grpc.xds.XdsChannelCredentials;
|
||||||
|
import io.netty.handler.ssl.SslContext;
|
||||||
|
import io.netty.handler.ssl.SslContextBuilder;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import javax.net.ssl.SSLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple xDS client that requests a greeting from the {@link HelloWorldServerXds}.
|
||||||
|
*/
|
||||||
|
public class HelloWorldClientXds {
|
||||||
|
private static final Logger logger = Logger.getLogger(HelloWorldClientXds.class.getName());
|
||||||
|
private final ManagedChannel channel;
|
||||||
|
private final GreeterGrpc.GreeterBlockingStub blockingStub;
|
||||||
|
|
||||||
|
/** Construct client connecting to HelloWorld server at {@code host:port}. */
|
||||||
|
public HelloWorldClientXds(String target, boolean useXdsCreds) throws SSLException {
|
||||||
|
this.channel =
|
||||||
|
Grpc.newChannelBuilder(
|
||||||
|
target,
|
||||||
|
useXdsCreds
|
||||||
|
? XdsChannelCredentials.create(InsecureChannelCredentials.create())
|
||||||
|
: InsecureChannelCredentials.create())
|
||||||
|
.build();
|
||||||
|
blockingStub = GreeterGrpc.newBlockingStub(this.channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown() throws InterruptedException {
|
||||||
|
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Say hello to server. */
|
||||||
|
public void greet(String name) {
|
||||||
|
logger.info("Will try to greet " + name + " ...");
|
||||||
|
HelloRequest request = HelloRequest.newBuilder().setName(name).build();
|
||||||
|
HelloReply response;
|
||||||
|
try {
|
||||||
|
response = blockingStub.sayHello(request);
|
||||||
|
} catch (StatusRuntimeException e) {
|
||||||
|
logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.info("Greeting: " + response.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Greet server. If provided, the second element of {@code args} is the name to use in the
|
||||||
|
* greeting.
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
String user = "xds-client";
|
||||||
|
boolean useXdsCreds = false;
|
||||||
|
if (args.length < 1 || args.length > 3) {
|
||||||
|
System.out.println("USAGE: HelloWorldClientXds target [name [--secure]]\n");
|
||||||
|
System.err.println(" target The xds target to connect to using the 'xds:' target scheme.");
|
||||||
|
System.err.println(" name The name you wish to include in the greeting request. Defaults to " + user);
|
||||||
|
System.err.println(
|
||||||
|
" '--secure' Indicates using xDS credentials otherwise defaults to insecure.");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
if (args.length > 1) {
|
||||||
|
user = args[1];
|
||||||
|
if (args.length == 3) {
|
||||||
|
useXdsCreds = args[2].toLowerCase().startsWith("--s");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HelloWorldClientXds client = new HelloWorldClientXds(args[0], useXdsCreds);
|
||||||
|
try {
|
||||||
|
client.greet(user);
|
||||||
|
} finally {
|
||||||
|
client.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 The gRPC Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.grpc.examples.helloworldxds;
|
||||||
|
|
||||||
|
import io.grpc.Server;
|
||||||
|
import io.grpc.examples.helloworld.GreeterGrpc;
|
||||||
|
import io.grpc.examples.helloworld.HelloReply;
|
||||||
|
import io.grpc.examples.helloworld.HelloRequest;
|
||||||
|
import io.grpc.stub.StreamObserver;
|
||||||
|
import io.grpc.xds.internal.sds.XdsServerBuilder;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An xDS-managed Server for the {@code Greeter} service.
|
||||||
|
*/
|
||||||
|
public class HelloWorldServerXds {
|
||||||
|
private static final Logger logger = Logger.getLogger(HelloWorldServerXds.class.getName());
|
||||||
|
private final int port;
|
||||||
|
private final boolean useXdsCreds;
|
||||||
|
private final String hostName;
|
||||||
|
private Server server;
|
||||||
|
|
||||||
|
public HelloWorldServerXds(int port, String hostName, boolean useXdsCreds) {
|
||||||
|
this.port = port;
|
||||||
|
this.hostName = hostName;
|
||||||
|
this.useXdsCreds = useXdsCreds;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void start() throws IOException {
|
||||||
|
XdsServerBuilder builder = XdsServerBuilder.forPort(port).addService(new HostnameGreeter(hostName));
|
||||||
|
if (useXdsCreds) {
|
||||||
|
builder = builder.useXdsSecurityWithPlaintextFallback();
|
||||||
|
}
|
||||||
|
server = builder.build().start();
|
||||||
|
logger.info("Server started, listening on " + port);
|
||||||
|
Runtime.getRuntime()
|
||||||
|
.addShutdownHook(
|
||||||
|
new Thread() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
|
||||||
|
System.err.println("*** shutting down gRPC server since JVM is shutting down");
|
||||||
|
try {
|
||||||
|
HelloWorldServerXds.this.stop();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
logger.log(Level.SEVERE, "During stop", e);
|
||||||
|
}
|
||||||
|
System.err.println("*** server shut down");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stop() throws InterruptedException {
|
||||||
|
if (server != null) {
|
||||||
|
server.shutdown().awaitTermination(30, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Await termination on the main thread since the grpc library uses daemon threads. */
|
||||||
|
private void blockUntilShutdown() throws InterruptedException {
|
||||||
|
if (server != null) {
|
||||||
|
server.awaitTermination();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Main launches the server from the command line. */
|
||||||
|
public static void main(String[] args) throws IOException, InterruptedException {
|
||||||
|
boolean useXdsCreds = false;
|
||||||
|
String hostName = null;
|
||||||
|
if (args.length < 1 || args.length > 3) {
|
||||||
|
System.out.println("USAGE: HelloWorldServerTls port [hostname [--secure]]");
|
||||||
|
System.err.println("");
|
||||||
|
System.err.println(" port The port to bind to.");
|
||||||
|
System.err.println(" hostname The name clients will see in greet responses. ");
|
||||||
|
System.err.println(" Defaults to the machine's hostname");
|
||||||
|
System.out.println(
|
||||||
|
" '--secure' Indicates using xDS credentials options; otherwise defaults to insecure credentials.");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
if (args.length > 1) {
|
||||||
|
hostName = args[1];
|
||||||
|
if (args.length == 3) {
|
||||||
|
useXdsCreds = args[2].toLowerCase().startsWith("--s");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final HelloWorldServerXds server =
|
||||||
|
new HelloWorldServerXds(Integer.parseInt(args[0]), hostName, useXdsCreds);
|
||||||
|
server.start();
|
||||||
|
server.blockUntilShutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 The gRPC Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.grpc.examples.helloworldxds;
|
||||||
|
|
||||||
|
import io.grpc.examples.helloworld.GreeterGrpc;
|
||||||
|
import io.grpc.examples.helloworld.HelloReply;
|
||||||
|
import io.grpc.examples.helloworld.HelloRequest;
|
||||||
|
import io.grpc.stub.StreamObserver;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/** Greeter implementation which replies identifying itself with its hostname. */
|
||||||
|
public final class HostnameGreeter extends GreeterGrpc.GreeterImplBase {
|
||||||
|
private static final Logger logger = Logger.getLogger(HostnameGreeter.class.getName());
|
||||||
|
|
||||||
|
private final String serverName;
|
||||||
|
|
||||||
|
public HostnameGreeter(String serverName) {
|
||||||
|
if (serverName == null || serverName.isEmpty()) {
|
||||||
|
serverName = determineHostname();
|
||||||
|
}
|
||||||
|
this.serverName = serverName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
|
||||||
|
HelloReply reply = HelloReply.newBuilder()
|
||||||
|
.setMessage("Hello " + req.getName() + ", from " + serverName)
|
||||||
|
.build();
|
||||||
|
responseObserver.onNext(reply);
|
||||||
|
responseObserver.onCompleted();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String determineHostname() {
|
||||||
|
try {
|
||||||
|
return InetAddress.getLocalHost().getHostName();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.INFO, "Failed to determine hostname. Will generate one", ex);
|
||||||
|
}
|
||||||
|
// Strange. Well, let's make an identifier for ourselves.
|
||||||
|
return "generated-" + new Random().nextInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
// Copyright 2020 The gRPC Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option java_package = "io.grpc.examples.helloworld";
|
||||||
|
option java_outer_classname = "HelloWorldProto";
|
||||||
|
option objc_class_prefix = "HLW";
|
||||||
|
|
||||||
|
package helloworld;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue