gRPC on the client side

admin 1 2025-01-13 编辑

gRPC on the client side

In this post, we will briefly describe gRPC and how it benefits inter-service communication.

Most inter-systems communication components that use REST serialize their payload in JSON. As of now, JSON lacks a widely-used schema validation standard: JSON Schema is not widespread. Standard schema validation allows delegating the validation to a third-party library and being done with it. Without one, we must fall back to manual validation in the code. Worse, we must keep the validation code in sync with the schema.

XML has schema validation out-of-the-box: an XML document can declare a grammar that it must conform to. SOAP, being based on XML, benefits from it too.

Other serialization alternatives have a schema validation option: e.g., Avro, Kryo and Protocol Buffers. Interestingly enough, gRPC uses Protobuf to offer RPC across distributed components:

gRPC is a modern open source high performance Remote Procedure Call (RPC) framework that can run in any environment. It can efficiently connect services in and across data centers with pluggable support for load balancing, tracing, health checking and authentication. It is also applicable in last mile of distributed computing to connect devices, mobile applications and browsers to backend services. -- Why gRPC?

Moreover, Protocol is a binary serialization mechanism, saving a lot of bandwidth. Thus, gRPC is an excellent option for inter-systems communication. But if all your components talk gRPC, how can simple clients call them? In this post, we will build a gRPC service and show how to call it from curl.

A simple gRPC service​

The gRPC documentation is exhaustive, so here's a summary:

  • gRPC is a Remote Procedure Call framework

  • It works across a wide range of languages

  • It relies on Protocol Buffers:

    Protocol buffers are Google’s language-neutral, platform-neutral, extensible mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages.

    -- Protocol Buffers

  • It's part of the CNCF portfolio and is currently in the incubation stage

Let's set up our gRPC service. We will use Java, Kotlin, Spring Boot, and a dedicated gRPC Spring Boot integration project. The project structure holds two projects, one for the model and one for the code. Let's start with the model project.

I didn't want something complicated; reusing a simple example is enough: the request sends a string, and the response prefixes it with Hello. We design this model in a dedicated Protobuf schema file:

syntax = "proto3";                                        //1package ch.frankel.blog.grpc.model;                       //2option java_multiple_files = true;                        //3option java_package = "ch.frankel.blog.grpc.model";       //3option java_outer_classname = "HelloProtos";              //3service HelloService {                                    //4    rpc SayHello (HelloRequest) returns (HelloResponse) {    }}message HelloRequest {                                    //5    string name = 1;                                      //6}message HelloResponse {                                   //7    string message = 1;                                   //6}
  1. Protobuf definition version
  2. Package
  3. Java-specific configuration
  4. Service definition
  5. Request definition
  6. Field definition. First comes the type, then the name, and finally, the order
  7. Response definition

We shall use Maven to generate the Java boilerplate code:

<project>  <dependencies>    <dependency>      <groupId>io.grpc</groupId>                         <!--1-->      <artifactId>grpc-stub</artifactId>      <version>${grpc.version}</version>    </dependency>    <dependency>      <groupId>io.grpc</groupId>                         <!--1-->      <artifactId>grpc-protobuf</artifactId>      <version>${grpc.version}</version>    </dependency>    <dependency>      <groupId>jakarta.annotation</groupId>              <!--1-->      <artifactId>jakarta.annotation-api</artifactId>      <version>1.3.5</version>      <optional>true</optional>    </dependency>  </dependencies>  <build>    <extensions>      <extension>        <groupId>kr.motd.maven</groupId>                 <!--2-->        <artifactId>os-maven-plugin</artifactId>        <version>1.7.1</version>      </extension>    </extensions>    <plugins>      <plugin>        <groupId>org.xolstice.maven.plugins</groupId>    <!--3-->        <artifactId>protobuf-maven-plugin</artifactId>        <version>${protobuf-plugin.version}</version>        <configuration>          <protocArtifact>com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}</protocArtifact>          <pluginId>grpc-java</pluginId>          <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>        </configuration>        <executions>          <execution>            <goals>              <goal>compile</goal>              <goal>compile-custom</goal>            </goals>          </execution>        </executions>      </plugin>    </plugins>  </build></project>
  1. Compile-time dependencies
  2. Sniff information about the Operating System. Used in the next plugin
  3. Generate Java code from the proto file

After compilation, the structure should look something like the following:

We can package the classes in a JAR and use it in a web app project. The latter is in Kotlin, but only because it's my favourite JVM language.

We only need a specific Spring Boot starter dependency to integrate gRPC endpoints with Spring Boot:

<span class="to

gRPC on the client side

上一篇: Understanding the Significance of 3.4 as a Root in Mathematics
下一篇: Rewriting the Apache response-rewrite plugin in Rust
相关文章