mirror of https://github.com/grpc/grpc-java.git
examples: add examples-orca (#9204)
This commit is contained in:
parent
e2f7e676cf
commit
45dd17c799
|
@ -36,6 +36,7 @@ $ VERSION_FILES=(
|
|||
examples/example-tls/build.gradle
|
||||
examples/example-tls/pom.xml
|
||||
examples/example-xds/build.gradle
|
||||
examples/example-orca/build.gradle
|
||||
)
|
||||
```
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
gRPC ORCA Example
|
||||
================
|
||||
|
||||
The ORCA example consists of a Hello World client and a Hello World server. Out-of-the-box the
|
||||
client behaves the same the hello-world version and the server behaves similar to the
|
||||
example-hostname. In addition, they have been integrated with backend metrics reporting features.
|
||||
|
||||
### Build the example
|
||||
|
||||
Build the ORCA hello-world example client & server. From the `grpc-java/examples/examples-orca`
|
||||
directory:
|
||||
```
|
||||
$ ../gradlew installDist
|
||||
```
|
||||
|
||||
This creates the scripts `build/install/example-orca/bin/custom-backend-metrics-client` and
|
||||
`build/install/example-orca/bin/custom-backend-metrics-server`.
|
||||
|
||||
### Run the example
|
||||
|
||||
To use ORCA, you have to instrument both the client and the server.
|
||||
At the client, in your own load balancer policy, you use gRPC APIs to install listeners to receive
|
||||
per-query and out-of-band metric reports.
|
||||
At the server, you add a server interceptor provided by gRPC in order to send per-query backend metrics.
|
||||
And you register a bindable service, also provided by gRPC, in order to send out-of-band backend metrics.
|
||||
Meanwhile, you update the metrics data from your own measurements.
|
||||
|
||||
That's it! In this example, we simply put all the necessary pieces together to demonstrate the
|
||||
metrics reporting mechanism.
|
||||
|
||||
1. To start the ORCA enabled example server on its default port of 50051, run:
|
||||
```
|
||||
$ ./build/install/example-orca/bin/custom-backend-metrics-server
|
||||
```
|
||||
|
||||
2. In a different terminal window, run the ORCA enabled example client:
|
||||
```
|
||||
$ ./build/install/example-orca/bin/custom-backend-metrics-client "orca tester" 1500
|
||||
```
|
||||
The first command line argument (`orca tester`) is the name you wish to include in
|
||||
the greeting request to the server and the second argument
|
||||
(`1500`) is the time period (in milliseconds) you want to run the client before it shut downed so that it will show
|
||||
more periodic backend metrics reports. You are expected to see the metrics data printed out. Try it!
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
plugins {
|
||||
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.17'
|
||||
// Generate IntelliJ IDEA's .idea & .iml project files
|
||||
id 'idea'
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven { // The google mirror is less flaky than mavenCentral()
|
||||
url "https://maven-central.storage-download.googleapis.com/maven2/" }
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
|
||||
def grpcVersion = '1.48.0-SNAPSHOT' // CURRENT_GRPC_VERSION
|
||||
def protocVersion = '3.19.2'
|
||||
|
||||
dependencies {
|
||||
implementation "io.grpc:grpc-protobuf:${grpcVersion}"
|
||||
implementation "io.grpc:grpc-services:${grpcVersion}"
|
||||
implementation "io.grpc:grpc-stub:${grpcVersion}"
|
||||
implementation "io.grpc:grpc-xds:${grpcVersion}"
|
||||
compileOnly "org.apache.tomcat:annotations-api:6.0.53"
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
task CustomBackendMetricsClient(type: CreateStartScripts) {
|
||||
mainClass = 'io.grpc.examples.orca.CustomBackendMetricsClient'
|
||||
applicationName = 'custom-backend-metrics-client'
|
||||
outputDir = new File(project.buildDir, 'tmp/scripts/' + name)
|
||||
classpath = startScripts.classpath
|
||||
}
|
||||
|
||||
task CustomBackendMetricsServer(type: CreateStartScripts) {
|
||||
mainClass = 'io.grpc.examples.orca.CustomBackendMetricsServer'
|
||||
applicationName = 'custom-backend-metrics-server'
|
||||
outputDir = new File(project.buildDir, 'tmp/scripts/' + name)
|
||||
classpath = startScripts.classpath
|
||||
}
|
||||
|
||||
applicationDistribution.into('bin') {
|
||||
from(CustomBackendMetricsClient)
|
||||
from(CustomBackendMetricsServer)
|
||||
fileMode = 0755
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
rootProject.name = 'example-orca'
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright 2022 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.orca;
|
||||
|
||||
import static io.grpc.examples.orca.CustomBackendMetricsLoadBalancerProvider.EXAMPLE_LOAD_BALANCER;
|
||||
|
||||
import io.grpc.Channel;
|
||||
import io.grpc.LoadBalancerRegistry;
|
||||
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 java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* A simple xDS client that requests a greeting from {@link CustomBackendMetricsServer}.
|
||||
* The client channel is configured to use an example load balancer policy
|
||||
* {@link CustomBackendMetricsLoadBalancerProvider} which integrates with ORCA metrics reporting.
|
||||
*/
|
||||
public class CustomBackendMetricsClient {
|
||||
private static final Logger logger = Logger.getLogger(CustomBackendMetricsClient.class.getName());
|
||||
|
||||
private final GreeterGrpc.GreeterBlockingStub blockingStub;
|
||||
|
||||
/** Construct client for accessing HelloWorld server using the existing channel. */
|
||||
public CustomBackendMetricsClient(Channel channel) {
|
||||
blockingStub = GreeterGrpc.newBlockingStub(channel);
|
||||
}
|
||||
|
||||
/** 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 first element of {@code args} is the name to use in the
|
||||
* greeting. The second argument is the target server.
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
String user = "orca tester";
|
||||
// The example defaults to the same behavior as the hello world example.
|
||||
// To receive more periodic OOB metrics reports, use duration argument to a longer value.
|
||||
String target = "localhost:50051";
|
||||
long timeBeforeShutdown = 1500;
|
||||
if (args.length > 0) {
|
||||
if ("--help".equals(args[0])) {
|
||||
System.err.println("Usage: [name [duration [target]]]");
|
||||
System.err.println("");
|
||||
System.err.println(" name The name you wish to be greeted by. Defaults to " + user);
|
||||
System.err.println(" duration The time period in milliseconds that the client application " +
|
||||
"wait until shutdown. Defaults to " + timeBeforeShutdown);
|
||||
System.err.println(" target The server to connect to. Defaults to " + target);
|
||||
System.exit(1);
|
||||
}
|
||||
user = args[0];
|
||||
}
|
||||
if (args.length > 1) {
|
||||
timeBeforeShutdown = Long.parseLong(args[1]);
|
||||
}
|
||||
|
||||
if (args.length > 2) {
|
||||
target = args[2];
|
||||
}
|
||||
|
||||
LoadBalancerRegistry.getDefaultRegistry().register(
|
||||
new CustomBackendMetricsLoadBalancerProvider());
|
||||
ManagedChannel channel = ManagedChannelBuilder.forTarget(target)
|
||||
.defaultLoadBalancingPolicy(EXAMPLE_LOAD_BALANCER)
|
||||
.usePlaintext()
|
||||
.build();
|
||||
try {
|
||||
CustomBackendMetricsClient client = new CustomBackendMetricsClient(channel);
|
||||
client.greet(user);
|
||||
Thread.sleep(timeBeforeShutdown);
|
||||
} finally {
|
||||
channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Copyright 2022 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.orca;
|
||||
|
||||
import io.grpc.ConnectivityState;
|
||||
import io.grpc.LoadBalancer;
|
||||
import io.grpc.LoadBalancerProvider;
|
||||
import io.grpc.LoadBalancerRegistry;
|
||||
import io.grpc.util.ForwardingLoadBalancer;
|
||||
import io.grpc.util.ForwardingLoadBalancerHelper;
|
||||
import io.grpc.xds.orca.OrcaOobUtil;
|
||||
import io.grpc.xds.orca.OrcaPerRequestUtil;
|
||||
import io.grpc.xds.shaded.com.github.xds.data.orca.v3.OrcaLoadReport;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Implements a test LB policy that receives ORCA load reports.
|
||||
* The load balancer mostly delegates to {@link io.grpc.internal.PickFirstLoadBalancerProvider},
|
||||
* in addition, it installs {@link OrcaOobUtil.OrcaOobReportListener} and
|
||||
* {@link OrcaPerRequestUtil.OrcaPerRequestReportListener} to be notified with backend metrics.
|
||||
*/
|
||||
final class CustomBackendMetricsLoadBalancerProvider extends LoadBalancerProvider {
|
||||
|
||||
static final String EXAMPLE_LOAD_BALANCER = "example_backend_metrics_load_balancer";
|
||||
|
||||
@Override
|
||||
public LoadBalancer newLoadBalancer(LoadBalancer.Helper helper) {
|
||||
return new CustomBackendMetricsLoadBalancer(helper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPolicyName() {
|
||||
return EXAMPLE_LOAD_BALANCER;
|
||||
}
|
||||
|
||||
private final class CustomBackendMetricsLoadBalancer extends ForwardingLoadBalancer {
|
||||
private LoadBalancer delegate;
|
||||
|
||||
public CustomBackendMetricsLoadBalancer(LoadBalancer.Helper helper) {
|
||||
this.delegate = LoadBalancerRegistry.getDefaultRegistry()
|
||||
.getProvider("pick_first")
|
||||
.newLoadBalancer(new CustomBackendMetricsLoadBalancerHelper(helper));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoadBalancer delegate() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
private final class CustomBackendMetricsLoadBalancerHelper
|
||||
extends ForwardingLoadBalancerHelper {
|
||||
private final LoadBalancer.Helper orcaHelper;
|
||||
|
||||
public CustomBackendMetricsLoadBalancerHelper(LoadBalancer.Helper helper) {
|
||||
this.orcaHelper = OrcaOobUtil.newOrcaReportingHelper(helper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoadBalancer.Subchannel createSubchannel(LoadBalancer.CreateSubchannelArgs args) {
|
||||
LoadBalancer.Subchannel subchannel = super.createSubchannel(args);
|
||||
// Installs ORCA OOB metrics reporting listener and configures to receive report every 1s.
|
||||
// The interval can not be smaller than server minimum report interval configuration,
|
||||
// otherwise it is treated as server minimum report interval.
|
||||
OrcaOobUtil.setListener(subchannel, new OrcaOobUtil.OrcaOobReportListener() {
|
||||
@Override
|
||||
public void onLoadReport(OrcaLoadReport orcaLoadReport) {
|
||||
System.out.println("Example load balancer received OOB metrics report:\n"
|
||||
+ orcaLoadReport);
|
||||
}
|
||||
},
|
||||
OrcaOobUtil.OrcaReportingConfig.newBuilder()
|
||||
.setReportInterval(1, TimeUnit.SECONDS)
|
||||
.build()
|
||||
);
|
||||
return subchannel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBalancingState(ConnectivityState newState, LoadBalancer.SubchannelPicker newPicker) {
|
||||
delegate().updateBalancingState(newState, new MayReportLoadPicker(newPicker));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoadBalancer.Helper delegate() {
|
||||
return orcaHelper;
|
||||
}
|
||||
}
|
||||
|
||||
private final class MayReportLoadPicker extends LoadBalancer.SubchannelPicker {
|
||||
private LoadBalancer.SubchannelPicker delegate;
|
||||
|
||||
public MayReportLoadPicker(LoadBalancer.SubchannelPicker delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoadBalancer.PickResult pickSubchannel(LoadBalancer.PickSubchannelArgs args) {
|
||||
LoadBalancer.PickResult result = delegate.pickSubchannel(args);
|
||||
if (result.getSubchannel() == null) {
|
||||
return result;
|
||||
}
|
||||
// Installs ORCA per-query metrics reporting listener.
|
||||
return LoadBalancer.PickResult.withSubchannel(
|
||||
result.getSubchannel(),
|
||||
OrcaPerRequestUtil.getInstance().newOrcaClientStreamTracerFactory(
|
||||
new OrcaPerRequestUtil.OrcaPerRequestReportListener() {
|
||||
@Override
|
||||
public void onLoadReport(OrcaLoadReport orcaLoadReport) {
|
||||
System.out.println("Example load balancer received per-rpc metrics report:\n"
|
||||
+ orcaLoadReport);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright 2022 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.orca;
|
||||
|
||||
import io.grpc.BindableService;
|
||||
import io.grpc.examples.helloworld.GreeterGrpc;
|
||||
import io.grpc.examples.helloworld.HelloReply;
|
||||
import io.grpc.examples.helloworld.HelloRequest;
|
||||
import io.grpc.Server;
|
||||
import io.grpc.ServerBuilder;
|
||||
import io.grpc.services.CallMetricRecorder;
|
||||
import io.grpc.services.MetricRecorder;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import io.grpc.xds.orca.OrcaMetricReportingServerInterceptor;
|
||||
import io.grpc.xds.orca.OrcaServiceImpl;
|
||||
import io.grpc.xds.shaded.com.github.xds.data.orca.v3.OrcaLoadReport;
|
||||
import java.io.IOException;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Server that manages startup/shutdown of a {@code Greeter} server.
|
||||
*/
|
||||
public class CustomBackendMetricsServer {
|
||||
private static final Logger logger = Logger.getLogger(CustomBackendMetricsServer.class.getName());
|
||||
|
||||
private Server server;
|
||||
private static Random random = new Random();
|
||||
private MetricRecorder metricRecorder;
|
||||
|
||||
private void start() throws IOException {
|
||||
/* The port on which the server should run */
|
||||
int port = 50051;
|
||||
|
||||
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||
metricRecorder = MetricRecorder.newInstance();
|
||||
// Configure OOB metrics reporting minimum report interval to be 1s. This allows client
|
||||
// configuration to be as short as 1s, suitable for test demonstration.
|
||||
BindableService orcaOobService =
|
||||
OrcaServiceImpl.createService(executor, metricRecorder, 1, TimeUnit.SECONDS);
|
||||
server = ServerBuilder.forPort(port)
|
||||
.addService(new GreeterImpl())
|
||||
// Enable OOB custom backend metrics reporting.
|
||||
.addService(orcaOobService)
|
||||
// Enable per-query custom backend metrics reporting.
|
||||
.intercept(OrcaMetricReportingServerInterceptor.getInstance())
|
||||
.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 {
|
||||
CustomBackendMetricsServer.this.stop();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
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 {
|
||||
CustomBackendMetricsServer server = new CustomBackendMetricsServer();
|
||||
server.start();
|
||||
server.blockUntilShutdown();
|
||||
}
|
||||
|
||||
class GreeterImpl extends GreeterGrpc.GreeterImplBase {
|
||||
|
||||
@Override
|
||||
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
|
||||
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
|
||||
OrcaLoadReport randomPerRpcMetrics = OrcaLoadReport.newBuilder()
|
||||
.setCpuUtilization(random.nextDouble())
|
||||
.setMemUtilization(random.nextDouble())
|
||||
.putUtilization("util", random.nextDouble())
|
||||
.putRequestCost("cost", random.nextDouble())
|
||||
.build();
|
||||
// Sets per-query backend metrics to a random test report.
|
||||
CallMetricRecorder.getCurrent()
|
||||
.recordMemoryUtilizationMetric(randomPerRpcMetrics.getMemUtilization())
|
||||
.recordCallMetric("cost", randomPerRpcMetrics.getRequestCostOrDefault("cost", 0.0))
|
||||
.recordUtilizationMetric("util", randomPerRpcMetrics.getUtilizationOrDefault("util", 0.0));
|
||||
System.out.println("Hello World Server updates RPC metrics data:\n" + randomPerRpcMetrics);
|
||||
|
||||
OrcaLoadReport randomOobMetrics = OrcaLoadReport.newBuilder()
|
||||
.setCpuUtilization(random.nextDouble())
|
||||
.setMemUtilization(random.nextDouble())
|
||||
.putUtilization("util", random.nextDouble())
|
||||
.build();
|
||||
// Sets OOB backend metrics to a random test report.
|
||||
metricRecorder.setCpuUtilizationMetric(randomOobMetrics.getCpuUtilization());
|
||||
metricRecorder.setMemoryUtilizationMetric(randomOobMetrics.getMemUtilization());
|
||||
metricRecorder.setAllUtilizationMetrics(randomOobMetrics.getUtilizationMap());
|
||||
System.out.println("Hello World Server updates OOB metrics data:\n" + randomOobMetrics);
|
||||
responseObserver.onNext(reply);
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2022 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