pull/3109/head
Lisa Carey 10 years ago
commit 6443f8f855
  1. 41
      Step_0.md
  2. 33
      Step_1.md
  3. 85
      Step_2.md
  4. 82
      Step_3.md

@ -1,41 +0,0 @@
# Step-0: define a service
This section presents an example of a simple service definition that receives
a message from a remote client. The message contains the user's name and
sends back a greeting to that person.
It's shown below in full; it's actually contained in separate file.
[helloworld.proto](src/main/proto/helloworld.proto).
```
syntax = "proto3";
package helloworld;
// The request message containing the user's name.
message HelloRequest {
optional string name = 1;
}
// The response message containing the greetings
message HelloReply {
optional string message = 1;
}
// The greeting service definition.
service Greeting {
// Sends a greeting
rpc hello (HelloRequest) returns (HelloReply) {
}
}
```
The service stanza of the message is an example of protobuf service IDL
(Interface Definition Language). Here, it defines a simple service that
receives a request containing a name and returns a response containing a
message.
Next, in [Step - 1](Step_1.md), we'll use protoc to generate client code from
this IDL.

@ -1,33 +0,0 @@
# Step-1: Generate a service client.
In this step, we use protoc to generate the Java Stub classes. A Stub is the
name gRPC uses for the code that initiates contact with a gRPC service running
remotely via the internet.
If you did not install protoc on your system, you can skip this step and move
onto the next one where we examine the generated code.
First, you'll need to build the protobuf plugin that generates the rpc
classes. `protoc` uses other tools called plugins to add additional features
to generated code.
The gRPC Java Stub classes are created using a gRPC Java plugin, but first the
plugin must be built and installed.
To build the plugin:
```
$ pushd external/grpc_java
$ make java_plugin
$ popd
```
To use it to generate the code:
```
$ mkdir -p src/main/java
$ protoc -I . helloworld.proto --plugin=protoc-gen-grpc=external/grpc_java/bins/opt/java_plugin \
--grpc_out=src/main/java \
--java_out=src/main/java
```
Next, in [Step - 2](Step_2.md), we'll use the generated Stub implementation to
write a client that uses the generated code to make a call to a service.

@ -1,85 +0,0 @@
# Step-2: Write a service client.
This step uses the generated code to write a simple client to access the hello
service. The full client is in [GreetingsClient.java](src/main/java/ex/grpc/GreetingsClient.java).
## Configuring the service to connect to.
The client contains uses a Stub to contact the service. The internet address
is configured in the client constructor. gRPC Channel is the abstraction over
transport handling; its constructor accepts the host name and port of the
service. The channel in turn is used to construct the Stub.
```
private final ChannelImpl channel;
private final GreetingGrpc.GreetingBlockingStub blockingStub;
public HelloClient(String host, int port) {
channel = NettyChannelBuilder.forAddress(host, port)
.negotiationType(NegotiationType.PLAINTEXT)
.build();
blockingStub = GreetingGrpc.newBlockingStub(channel);
}
```
## Obtaining a greeting
The greet method uses the stub to contact the service and obtain a greeting.
It:
- constructs a request
- obtains a reply from the stub
- prints out the greeting
```
public void greet(String name) {
logger.debug("Will try to greet " + name + " ...");
try {
Helloworld.HelloRequest request = Helloworld.HelloRequest.newBuilder().setName(name).build();
Helloworld.HelloReply reply = blockingStub.hello(request);
logger.info("Greeting: " + reply.getMessage());
} catch (RuntimeException e) {
logger.log(Level.WARNING, "RPC failed", e);
return;
}
}
```
## Running from the command line
The main method puts together the example so that it can be run from a command
line.
```
/* Access a service running on the local machine on port 50051 */
HelloClient client = new HelloClient("localhost", 50051);
String user = "world";
if (args.length > 1) {
user = args[1];
}
client.greet(user);
```
It can be built as follows.
```
$ mvn package
```
It can also be run, but doing so now would end up a with a failure as there is
no server available yet. The [next step](Step_3.md), describes how to
implement, build and run a server that supports the service description.
## Notes
- The client uses a blocking stub. This means that the RPC call waits for the
server to respond, and will either return a response or raise an exception.
- gRPC Java has other kinds of stubs that make non-blocking calls to the
server, where the response is returned asynchronously. Usage of these stubs
is a more advanced topic and will be described in later steps.

@ -1,82 +0,0 @@
# Step-3: Implement a server.
This step extends the generated server skeleton code to write a simple server
that provides the hello service. This introduces two new classes:
- a service implementation [GreetingsImpl.java](src/main/java/ex/grpc/GreetingsImpl.java).
- a server that hosts the service implementation and allows access over the network: [GreetingsServer.java](src/main/java/ex/grpc/GreetingsServer.java).
## Service implementation
[GreetingsImpl.java](src/main/java/ex/grpc/GreetingsImpl.java)
implements the behaviour we require of our GreetingService. There are a
number of important features of gRPC being used here:
```
public void hello(Helloworld.HelloRequest req,
StreamObserver<Helloworld.HelloReply> responseObserver) {
Helloworld.HelloReply reply = Helloworld.HelloReply.newBuilder().setMessage(
"Hello " + req.getName()).build();
responseObserver.onValue(reply);
responseObserver.onCompleted();
}
```
- it provides a class `GreetingsImpl` that implements a generated interface `GreetingsGrpc.Greetings`
- `GreetingsGrpc.Greetings` declares the method `hello` that was declared in the proto [IDL](src/main/proto/helloworld.proto)
- `hello's` signature is typesafe:
hello(Helloworld.HelloRequest req, StreamObserver<Helloworld.HelloReply> responseObserver)
- `hello` takes two parameters:
`Helloworld.HelloRequest`: the request
`StreamObserver<Helloworld.HelloReply>`: a response observer, an interface to be called with the response value
- to complete the call
- the return value is constructed
- the responseObserver.onValue() is called with the response
- responseObserver.onCompleted() is called to indicate that no more work will done on the RPC.
## Server implementation
[GreetingsServer.java](src/main/java/ex/grpc/GreetingsServer.java) shows the
other main feature required to provde the gRPC service; how to allow a service
implementation to be accessed from the network.
```
private void start() throws Exception {
server = NettyServerBuilder.forPort(port)
.addService(GreetingsGrpc.bindService(new GreetingsImpl()))
.build();
server.startAsync();
server.awaitRunning(5, TimeUnit.SECONDS);
}
```
- it provides a class `GreetingsServer` that holds a `ServerImpl` that will run the server
- in the `start` method, `GreetingServer` binds the `GreetingsService` implementation to a port and begins running it
- there is also a `stop` method that takes care of shutting down the service and cleaning up when the program exits
## Build it
This is the same as before: our client and server are part of the same maven
package so the same command builds both.
```
$ mvn package
```
## Try them out
We've added simple shell scripts to simplifying running the examples. Now
that they are built, you can run the server with:
```
$ ./run_greetings_server.sh
```
and in another terminal window confirm that it receives a message.
```
$ ./run_greetings_client.sh
```
Loading…
Cancel
Save