This is the 16th day of my participation in the August More Text Challenge. For details, see: August More Text Challenge

Author: Tom brother wechat public account: Micro technology

1, the introduction of

In gRPC, a client application can directly call the methods of a server application on a different machine as if it were a local object, making it easier to create distributed applications and services.

GRPC is designed based on the HTTP/2 standard, bringing things like bidirectional streaming, flow control, header compression, multiplexing requests over a single TCP connection, and so on. These features enable it to perform better on mobile devices and save power and space.

There are many excellent open source projects using gRPC as a means of communication, such as Kubernetes, SkyWalking, Istio and so on. Dubbo has even begun to support the gRPC protocol since version 2.7.5

GRPC provides two new RPC invocation modes:

  • The common RPC invocation mode is request-response mode.

  • HTTP/2.0 based streaming invocation.

GRPC service invocation supports synchronous and asynchronous modes, RPC and streaming modes, which can meet the service requirements to the greatest extent.

The streaming mode can make full use of the multiplexing function of HTTP/2.0 protocol, realize the parallel bidirectional data transmission on an HTTP link, effectively solve the problem of one-way data transmission in HTTP/ 1.x, and make full use of the performance of a single link while greatly reducing the HTTP connection. It is comparable to traditional RPC private persistent connection protocol: fewer links, higher performance.

GRPC network I/O communication based on Netty construction, service call bottom unified use asynchronous mode, synchronous call is done on the basis of asynchronous upper encapsulation. Therefore, gRPC asynchronous is more thorough, to improve the I/O intensive business throughput and reliability has a great help.

Netty uses the multiplexed Reactor thread model: Based on Linux epoll and Selector, one I/O thread can process hundreds of links in parallel, which solves the problem of traditional synchronous I/O communication thread expansion. NIO addresses asynchrony at the communication level and is not necessarily related to asynchrony of service invocation.

Application scenario:

In the early stage of the company, in order to meet the needs of rapid business iteration, technology selection is optional, and development in multiple languages is often encountered, such as Java, Python, PHP,.NET, etc., and different business systems are built. Now considering the platform technology upgrade, some basic functions need to be consolidated and several micro-service centers (such as user center and authority center) should be built. Based on this background, how to do technology selection, we can consider using gRPC.

GRPC implementation steps:

  • Define a service, specifying the methods (including parameters, return types) that can be called remotely

  • Implement this interface on the server side and run a gRPC server to handle client requests

  • Implement a Stub Stub on the client to initiate a remote method call

GRPC clients and servers can run and interact in multiple languages and environments! We can easily create a gRPC server in Java and create a gRPC client in Java, Go, Python, Ruby to access it.

2. Proto interface specification

Add the following dependencies to pom.xml:

<dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-netty</artifactId>
    <version>${grpc.version}</version>
</dependency>
<dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-protobuf</artifactId>
    <version>${grpc.version}</version>
</dependency>
<dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-stub</artifactId>
    <version>${grpc.version}</version>
</dependency>

Copy the code
  • Introduce the GRPC-Protobuf dependency, using Protobuf as the serialization library.

  • Introduce the GRPC-Stub dependency and use GRPC Stub as the client.

Add Maven dependencies

<build> <extensions> <extension> <groupId>kr.motd.maven</groupId> <artifactId>os-maven-plugin</artifactId> <version> 1.5.0.final </version> </extension> </extensions> <plugins> . < the groupId > org. Xolstice. Maven plugins < / groupId > < artifactId > protobuf - maven - plugin < / artifactId > < version > 0.5.1 < / version > < configuration > < protocArtifact > com. Google. Protobuf: protoc: 3.5.1 track of 1: exe: ${OS. Detected. Classifier} < / protocArtifact > <pluginId>grpc-java</pluginId> The < pluginArtifact > IO. GRPC: protoc - gen - GRPC - Java: 1.15.0: exe: ${OS. Detected. Classifier} < / pluginArtifact > < / configuration > <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> </plugins> </build>Copy the code
  • The OS-maven-plugin is introduced to obtain parameters from the OS system. Because it is needed to get the os.detected. Classifier parameter from the OS system.

  • Protobuf-maven-plugin is introduced to implement the protobuf file in the proto directory to generate Service and Message classes.

Define the PROto interface specification

service UserService {
    rpc query (UserRequest) returns (UserResponse);
}

message UserRequest {
    string name = 1;

}
message UserResponse {
    string name = 1;
    int32 age = 2;
    string address = 3;
}

Copy the code

Click the “compile” button in IDEA to compile the spring-boot-Bulking-grpc-proto project, and execute protobuf-Maven-plugin to generate it. The results are shown in the figure below:

3. Server implementation

Define annotation classes for scanning Grpc related interface services

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface GrpcService {
}

Copy the code

Interface implementation class

@GrpcService public class UserService extends UserServiceGrpc.UserServiceImplBase { @Override public void Query (UserRequest request, StreamObserver<UserResponse> responseObserver) {system.out.println (" UserService received parameters, Name: "+ request.getName()); UserResponse Response = userResponse.newBuilder ().setName(" microtech ").setage (30).setAddress(" Shanghai ").build(); responseObserver.onNext(response); responseObserver.onCompleted(); }}Copy the code

Start the GRPC server, listen on port 9091, and add the interface implementation class defined by Proto

@Component public class ServiceManager { private Server server; private int grpcServerPort = 9091; public void loadService(Map<String, Object> grpcServiceBeanMap) throws IOException, InterruptedException { ServerBuilder serverBuilder = ServerBuilder.forPort(grpcServerPort); / / the annotation scanning way, add services for (Object bean: grpcServiceBeanMap. The values ()) {serverBuilder. The addService (BindableService bean); Println (bean.getClass().getSimplename () + "is regist in Spring Boot!" ); } server = serverBuilder.build().start(); System.out.println("grpc server is started at " + grpcServerPort); // Add a hook for when the JVM process exits, AddShutdownHook (new Thread() {@override public void run() {system.err. Println ("*** ") shutting down gRPC server since JVM is shutting down"); if (server ! = null) { server.shutdown(); } system.err. Println ("*** server shut down!!!!") ); }}); server.awaitTermination(); }}Copy the code

The Server is started successfully

4. Client invocation

Defines a Stub instance of the interface that is used to initiate a remote service call

@Configuration public class GrpcServiceConfig { @Bean public ManagedChannel getChannel() { ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 9091) .usePlaintext() .build(); return channel; } @Bean public HelloServiceGrpc.HelloServiceBlockingStub getStub1(ManagedChannel channel) { return HelloServiceGrpc.newBlockingStub(channel); } @Bean public UserServiceGrpc.UserServiceBlockingStub getStub2(ManagedChannel channel) { return UserServiceGrpc.newBlockingStub(channel); }}Copy the code

Restful interface call, visit: http://localhost:8098/query

@requestMapping ("/query") public String Query () {UserRequest Request = userRequest.newBuilder ().setName(" micro technology ") .build(); UserResponse userResponse = userServiceBlockingStub.query(request); String result = String.format("name:%s , age:%s , address:%s ", userResponse.getName(), userResponse.getAge(), userResponse.getAddress()); System.out.println(result); return result; }Copy the code

Starter components out of the box

The gRPC community has not yet provided a Spring Boot Starter library to simplify our gRPC configuration. Nevertheless the home has big god already opened source.

Address: github.com/yidongnan/g…

Features:

  • In a Spring Boot application, an embedded gRPC service is automatically configured and run with @grpcService

  • Use @grpcclient to automatically create and manage your gRPC Channels and Stubs

  • Support for Spring Cloud (register with Consul or Eureka or Nacos and get gRPC service information)

  • Support Spring Sleuth for link tracing (requires separate introduction of Brave-Instrumentation – GRPC)

  • You can set a global interceptor for the server and a single interceptor for the client

  • Support Spring ws-security

  • Support for METRIC (based on Micrometer/ACTUATOR)

  • Apply also to (non-shaded) GRPC-netty

6, the project source address

https://github.com/aalansehaiyang/spring-boot-bulking three modules:  spring-boot-bulking-grpc-proto spring-boot-bulking-grpc-client spring-boot-bulking-grpc-serverCopy the code

Author introduction: Tom brother, computer graduate student, recruited into Ali, P7 technology expert, patent, CSDN blog expert. In charge of e-commerce transactions, community fresh, traffic marketing, Internet finance and other businesses, many years of first-line team management experience