API Protocol - GRPC
package com.food.ordering.system.saga;
public interface SagaStep<T> {
void process(T data);
void rollback(T data);
}
Steps
- Define a service in a
.proto
file. - Generate server and client code using the protocol buffer compiler.
- Use the Java gRPC API to write a simple client and server for your service.
Define a service in a .proto file
syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples.routeguide";
option java_outer_classname = "RouteGuideProto";
option objc_class_prefix = "RTG";
package routeguide;
// Interface exported by the server.
service RouteGuide {
rpc GetFeature(Point) returns (Feature) {}
rpc ListFeatures(Rectangle) returns (stream Feature) {}
rpc RecordRoute(stream Point) returns (RouteSummary) {}
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}
message Point {
int32 latitude = 1;
int32 longitude = 2;
}
message Rectangle {
// One corner of the rectangle.
Point lo = 1;
// The other corner of the rectangle.
Point hi = 2;
}
message Feature {
// The name of the feature.
string name = 1;
// The point where the feature is detected.
Point location = 2;
}
message FeatureDatabase {
repeated Feature feature = 1;
}
message RouteNote {
// The location from which the message is sent.
Point location = 1;
// The message to be sent.
string message = 2;
}
message RouteSummary {
// The number of points received.
int32 point_count = 1;
// The number of known features passed while traversing the route.
int32 feature_count = 2;
// The distance covered in metres.
int32 distance = 3;
// The duration of the traversal in seconds.
int32 elapsed_time = 4;
}
Generate Java Code from .proto File
Use the protoc
compiler to generate the Java classes from your .proto
file.
Using Maven
Add the following plugin to your pom.xml
&amp;amp;amp;lt;note&amp;amp;amp;gt; &amp;amp;amp;lt;/note&amp;amp;amp;gt;
<note><p></p><p>Don't forget me this weekend!</p> </note>
Implement the Server
Create a class to implement your gRPC service.
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;
public class HelloWorldServer {
private final int port = 50051;
private final Server server;
public HelloWorldServer() {
server = ServerBuilder.forPort(port)
.addService(new GreeterImpl())
.build();
}
public void start() throws IOException {
server.start();
System.out.println("Server started, listening on " + port);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.err.println("*** shutting down gRPC server since JVM is shutting down");
HelloWorldServer.this.stop();
System.err.println("*** server shut down");
}));
}
public void stop() {
if (server != null) {
server.shutdown();
}
}
public static void main(String[] args) throws IOException, InterruptedException {
final HelloWorldServer server = new HelloWorldServer();
server.start();
server.blockUntilShutdown();
}
private void blockUntilShutdown() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
}
static class GreeterImpl extends GreeterGrpc.GreeterImplBase {
@Override
public void sayHello(HelloRequest req, StreamObserver responseObserver) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
}
Implement the Client
Create a class to call the gRPC service.
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
public class HelloWorldClient {
private final GreeterGrpc.GreeterBlockingStub blockingStub;
public HelloWorldClient(ManagedChannel channel) {
blockingStub = GreeterGrpc.newBlockingStub(channel);
}
public void greet(String name) {
HelloRequest request = HelloRequest.newBuilder().setName(name).build();
HelloReply response = blockingStub.sayHello(request);
System.out.println("Greeting: " + response.getMessage());
}
public static void main(String[] args) throws Exception {
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50051)
.usePlaintext()
.build();
try {
HelloWorldClient client = new HelloWorldClient(channel);
client.greet("world");
} finally {
channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
}
}
}
Types of GRPC
-
Simple RPC
-
This is the simplest communication pattern by gRPC. Here, the client sends a single message to the server and receives a single message. As shown in the figure below, inside the stream, only one binary message is going in both request and response.
-
-
-
Server-Streaming RPC
-
Unlike in the simple RPC pattern, in server-streaming RPC, the server sends back a sequence of responses when a request is received from the client. This sequence of response messages are sent inside the same HTTP stream initiated by the client. As shown in the diagram below, the server waits until it receives the message from the client and sends multiple response messages as framed messages. At the end, the server concludes the stream by sending the trailing metadata with the call status details.
-
-
-
Client-Streaming RPC
-
In the client-streaming RPC pattern, the client sends multiple messages to the server and the server sends only one message in return. Similar to the patterns discussed above, all these messages are passed inside one HTTP stream initiated by the client. The figure below illustrates how multiple messages flow through the stream. This stream can last until the end of RPC.
-
BiDirectional Streaming RPC
In bidirectional streaming RPC, both the client and server send a stream of messages to each other. The client sets up the HTTP stream by sending header frames. Once the connection is set up, both the client and server can send messages simultaneously without waiting for the other to finish. The communication happens based on the logic of the gRPC client and server.