This is a creation in Article, where the information may have evolved or changed.
GRPC is based on the protocol buffers3.0 protocol.
This article will introduce you to GRPC and protocol buffers. GRPC can use the protocol buffers as its IDL (interface description) and its underlying message interchange format. If you are new to GRPC and protocol buffers, please read on! If you just want to see GRPC first, please see our QuickStart.
Guide
In Grpc, a client application can invoke a method directly on a server application on a different machine, as if it were a local object, making it easier for you to create distributed applications and services. Like many RPC systems, GRPC is based on the idea of defining services, specifying methods that can be called remotely using their parameters and return types. On the server side, the server implements this interface and runs the GRPC server to handle client calls. On the client side, the client has a stub (referred to as a client for some languages) that provides the same method as the server.
GRPC clients and servers can run and interact in a variety of environments, from servers inside Google to your own apps, and can be written in any GRPC-supported language. So, for example, you can easily create a Java-developed service that uses Go,python or a client in Ruby. In addition, the latest Google APIs would have grpc versions of their interfaces, letting you easily build Google Functiona Lity (function) into your applications.
Protocol buffer Version
Although protocol buffer has been available for open source users for some time, our example uses the new style of Proto3 protocol buffer, which has a slightly simplified syntax, some useful new features, and supports more languages. This is currently available for Java,c ++,python,objective-c,c#,lite-runtime (Android Java), Ruby and JavaScript protocol buffer Github Repo, And the Go language auto-generated from golang/protobuf GitHub, with more languages in development. You can view more content in the Proto3 language guide and the reference documentation for each supported language (if available), and you can see the main differences from the current default version in the release notes. More Proto3 documents to be launched soon.
Generally, although you can use Proto2 (the current default protocol version of buffer), we recommend that you use the PROTO3 protocol-based GRPC because it allows you to use the full range of GRPC-supported languages, and avoid compatibility issues with the Proto2 client and the Proto3 server, and vice versa.
Note: Because Proto2 only provides a message definition, it does not provide a definition for the service interface.
Service definition
GRPC Concepts
Like many RPC systems, GRPC is based on the idea of defining a service, specifying methods that can be called remotely using its parameters and return types. By default, GRPC uses the protocol buffers as the interface Definition language (IDL), which describes the service interface and structure of payload messages.
service HelloService { rpc SayHello (HelloRequest) returns (HelloResponse);}message HelloRequest { string greeting = 1;}message HelloResponse { string reply = 1;}
pf3.0 an interface definition appears.
GRPC defines four types of service interfaces:
- Unary RPC, the client sends a request to the server and gets a response, just like a normal function call.
rpc SayHello(HelloRequest) returns (HelloResponse){}
- Server stream RPC, client sends an Object Server side returns a stream (streaming message)
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){}
- Client-side streaming RPC, the client sends a stream (streaming message) to the server to return an object.
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {}
- Bidirectional stream RPC
Where both parties send a sequence of messages using read-write streams. Two streams run independently, so the client and server can read and write in the order they prefer: for example, the server may wait for all client messages to be received before writing the response, or alternately read the message and then write the message, or read and write other combinations. The order of messages in each stream is preserved.
Similar to WebSocket (long connection), the client can request messages to the server side, which can also request messages from the client.
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){}
Using the API
Starting with the service definition in the. proto file, GRPC provides a protocol buffer compiler plug-in that generates client and server-side code. GRPC users typically invoke these APIs on the client and implement the appropriate APIs on the server side.
- On the server side, the server implements the service declaration method and runs the GRPC server to handle client calls. GRPC Infrastructure decodes incoming requests, executes service methods, and encodes service responses.
- On the client side, the client has a local method definition called stub (for some languages, the preference is the client), which implements the same method as the service. The client can then call these methods directly on the local object, including the parameters of the call in the appropriate protocol buffer message type-GRPC after the request is sent to the server and returned to the server's protocol buffer response.
Synchronous and asynchronous
Synchronous RPC calls are blocked until the response is returned from the server that is closest to the procedure call that RPC craves (almost this meaning). On the other hand, the network is inherently asynchronous, and in many cases it is useful to start RPC without blocking the current thread.
The GRPC programming surface in most languages contains both synchronous and asynchronous languages. You can find more content in the tutorials and reference documents for each language (the full reference document is coming soon).
RPC Life cycle
Now let's take a closer look at what happens when the GRPC client calls the Grpc server method. We do not view implementation details and can learn more in specific language pages.
One-dollar RPC
The client sends a single request to the server and obtains a single response, just like a normal function call.
Once the client invokes a method on the Stub/client object, it notifies the server that the RPC client's metadata is used for this call, the method name, and the specified age (if configured)
The server can then immediately send back its initial metadata (which must be sent before any response) or wait for the client's request message-determined by the application who executes first.
Once the server has a client request message, it does whatever it takes to create and populate its response. The response (if successful) is then returned to the client, along with the status details (status code and optional status messages) and optional trailing metadata.
- The status is OK, the client gets the response, and the client finishes all calls.
Server Stream RPC
Server stream RPC is similar to our simple example in that the server sends back the response stream after the client request message is fetched. After all responses are sent back, the server-side status information (status code and optional status messages) and optional trailing metadata are sent back to completion. The client finishes until all the responses to the server are received.
Client-side Streaming RPC
Client stream RPC is also similar to our simple example, except that the client sends the request stream to the server instead of a single request. The server returns a single response, usually but does not necessarily return a response after all clients have received the request, along with its status details and optional trailing metadata.
Bidirectional stream RPC
In two-way streaming RPC, calls originate with the client calling the method and then the server-side receives the client's metadata, the method name, and the invocation period. The server can also choose to send back its initial metadata or wait for the client to start sending requests.
What happens next depends on the application because the client and the server can run completely independently in any sequential read and write-flow. Therefore, for example, the server may wait until all client messages are received before writing the response, or the server and client may "ping-pong": the server gets the request, then sends a response, and then the client sends another request based on the response, and so on.
Due Date and timeout
GRPC allows the client to specify the time to wait for the RPC to finish before the RPC service call terminates, otherwise error deadline_exceeded is displayed. On the server side, the server can query whether a particular RPC timed out, or how much time is left to complete the RPC call.
How to specify a period or time-out varies by language-for example, not all languages have a default deadline, some language APIs work at a deadline (fixed point-in-time), and some language APIs work overtime (over time).
RPC termination
In Grpc, both the client and the server are relatively independent and locally determined that the local call succeeds, and that the conclusion may not match the other end. This means, for example, that you can successfully complete an RPC return on the server side ("I have sent all my replies"), but failed on the client ("Reply after my due date"). The server can also decide to complete before the client sends all requests.
Canceling RPC Calls
The client or server can cancel the RPC at any time. Cancellation is terminated immediately so that no work can be done. It is not an "undo": Modifications before cancellation are not rolled back.
Meta data
Metadata is information about a specific RPC invocation (such as authentication details) in the form of a key-value pair, where the key is a string, and the value is usually a string (but can be binary data). Metadata is opaque to the GRPC itself-it allows the client to provide information associated with a call to the server, and vice versa.
Access to metadata depends on the language in which it is dependent.
Channel
The GRPC channel provides a connection to the GRPC server on the specified host and port, and is used when creating client stubs (or only "clients" in some languages). Clients can specify channel parameters to modify the default behavior of GRPC, such as turning message compression on and off. The channel has a status, including connection and idle. > Grpc How to deal with the closed channel is related to language. Some languages also allow query channel state.
Quick Start
Download example
➜ # Clone the repository at the latest release to get the example code:➜ git clone -b v1.4.0 https://github.com/grpc/grpc-java➜ # Navigate to the Java examples:➜ cd grpc-java/examples
-b v1.4.0
Indicates that this version is specified and the version is 1.4.0
not specified by default master
.
Run a GRPC application
Compile the server side and client, this step takes a long time,
➜ ./gradlew installDist
To run the server:
➜ ./build/install/examples/bin/hello-world-server六月 25, 2017 6:58:58 下午 io.grpc.examples.helloworld.HelloWorldServer start信息: Server started, listening on 50051
To run the client:
➜./build/install/examples/bin/hello-world-client六月 25, 2017 6:59:08 下午 io.grpc.examples.helloworld.HelloWorldClient greet信息: Will try to greet world ...六月 25, 2017 6:59:09 下午 io.grpc.examples.helloworld.HelloWorldClient greet信息: Greeting: Hello world
Modify the GRPC service
Enter the src/main/proto/
directory, modify helloworld.proto
the file, add a SayHelloAgain
method,
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) {} // Sends another greeting rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}}// The request message containing the user's name.message HelloRequest { string name = 1;}// The response message containing the greetingsmessage HelloReply { string message = 1;}
helloworld.proto
A method is added to the file SayHelloAgain
, and the HelloRequest
parameter is returned HelloReply
.
Modify the server code to increase SayHelloAgain
the implementation of the method
recompiling the. prto file will regenerate the client, the service-side code, and also regenerate the serialization, we add a method to the server to add just the helloworld.proto
SayHelloAgain
implementation of the file:
In the src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java
file add sayHelloAgain
method implementation:
private class GreeterImpl extends GreeterGrpc.GreeterImplBase { @Override public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) { HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build(); responseObserver.onNext(reply); responseObserver.onCompleted(); } @Override public void sayHelloAgain(HelloRequest req, StreamObserver<HelloReply> responseObserver) { HelloReply reply = HelloReply.newBuilder().setMessage("Hello again " + req.getName()).build(); responseObserver.onNext(reply); responseObserver.onCompleted(); }}...
Modify Client
Modify src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java
the file to increase blockingStub.sayHelloAgain
the call.
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()); try { response = blockingStub.sayHelloAgain(request); } catch (StatusRuntimeException e) { logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus()); return; } logger.info("Greeting: " + response.getMessage());}
Compiling files, re-executing
➜ ./gradlew installDist
To run the server:
➜ ./build/install/examples/bin/hello-world-server
To run the client:
➜ ./build/install/examples/bin/hello-world-client
Client print:
➜ ./build/install/examples/bin/hello-world-client六月 25, 2017 7:43:29 下午 io.grpc.examples.helloworld.HelloWorldClient greet信息: Will try to greet world ...六月 25, 2017 7:43:29 下午 io.grpc.examples.helloworld.HelloWorldClient greet信息: Greeting: Hello world六月 25, 2017 7:43:30 下午 io.grpc.examples.helloworld.HelloWorldClient greet信息: Greeting: Hello again world
Summarize
To run a simple grpc, first you need to learn the following three steps:
- Define a service with a. Proto file (defines the message body and the service interface)
- Use the protocol buffer compiler to compile the. proto file and to generate the client and server code (you cannot use the PROTOC directive because GRPC is used based on protocol buffer3.0, maven and gradle all provide the corresponding compilers, and PROTOC directives are protocol buffer2.0 instructions).
- Write your own client and service side (the server side writes an additional interface implementation).
This is how the underlying processes of all RPC frameworks are found.
Resources
Official address
Website Java Quick Guide
GitHub Address
Protocol buffer3.0 Protocol