Grpc simple implementation based on Golang and Java

Source: Internet
Author: User

Source connection: Learn about RPC and GRPC simple implementations based on Golang and Java

One: What is RPC

  • Introduction: Rpc:remote Procedure Call, remote procedure invocation. In a nutshell, data interaction between two processes. The interface service on the normal server is provided to the client (which is the browser in web development) or itself, that is, the local procedure call. And the local procedure call is the opposite: If two server is not in a process how to do data interaction? Use RPC. In particular, the large number of microservices practice, the call between services and services is inevitable, RPC is particularly important.

  • principle: in the computer world, regardless of which technology is used, the core is the operation of the data. RPC is simply a dimension of the operation of the data. The problem solved is essentially the transmission of data between different processes. Say more, you need to understand the knowledge of the network model, seven or four layers five layers. This is not the focus of this article. What we call RPC generally refers to the data interaction with the TCP protocol at the transport layer, as well as many mature HTTP-based frameworks.

    Misappropriation of the network on a picture description:

    GRPC process

    Describes the complete invocation process for an RPC:

    1:client initiates a method invocation request to the client stub.

    When the 2:client stub receives the request, it encodes the method name, request parameters, and so on.

    The 3:client stub uses the socket through the configured IP and port to initiate requests to remote server servers over the network.

    4: The remote server receives the request and decodes the deserialization request information.

    5:server the request information to the server Stub,server stub to find the corresponding local real-world method implementation.

    6: The local method processes the call request and gives the returned data to the server stub.

    The 7:server stub serializes the data encoding to the operating system kernel, using the socket to return the data.

    The 8:client end socket receives the return information of the remote server.

    The 9:client stub decodes the information and deserializes it.

    10:client received the information returned by the remote server.

    There is a stub (stub) concept in the. Stubs are responsible for receiving local method calls and delegating them to their specific implementation objects. The server stub is also known as skeleton (skeleton). Can be understood as a proxy class. In fact, Java-based RPC framework stubs are basically using dynamic proxies. What we call client side and server side in RPC is also generally a relative concept.

    The so-called RPC framework encapsulates the process of 2-9 in the above process, allowing developers to invoke remote methods just as they would call local methods.

Second: Common RPC frame selection

    • Duboo:

      Ali Open source TCP-based RPC framework is basically the most widely used development framework in domestic production environment. Use zookeeper to do service registration and discovery, use Netty to do network communication. Unfortunately not across languages, currently only Java is supported.

    • Thrift:

      Facebook's open source, cross-lingual RPC framework that defines RPC interfaces and data types through IDL, using the thrift compiler to generate implementations of different languages. It is said to be the best-performing RPC framework at the moment, but not used.

    • GRPC:

      That's the point we're going to talk about today. GRPC is Google's Open source product, a universal RPC framework across languages, written in the go language. The Java language application also uses the Netty to do the network communication, go uses the goroutine to do the network communication. The serialization approach uses Google's own open source protobuf. Requests the call and returns the stream using HTTP2.

    • Springcloud:

      Springcloud is not an RPC framework, it is a solution to a microservices governance in the spring family, and is a collection of a series of frameworks. But in this scenario, the communication between MicroServices uses a RESTful API based on HTTP, using Eureka or consul for service registration and discovery, and a remote invocation of the service using the declarative client feign. This series of functions is combined to form a complete set of remote service invocations.

How to choose:

I recommend Dubbo if the company project uses Java and is not involved in cross-language, and the scale is not too big to be difficult to govern. If the project is large and the service calls are complex, I recommend Springcloud.

If cross-language involved, I recommend GRPC, which is currently our choice. Even if the thrift performance is grpc twice times, but there is no way, it has a good father, now our development environment to consider the most or ecological.

Three: the principle of GRPC

An RPC framework must have two basic components: the serialization of data and the way the process communicates with each other.

For the serialization Grpc, the Protobuf of the home company's open source was adopted. What is PROTOBUF? Let's take a look at most of the explanations on the Web:

Google Protocol Buffer (abbreviated as PROTOBUF) is a lightweight and efficient structured data storage format, platform-Independent, language-independent, extensible, and can be used in communication protocols and data storage areas.

There are several key points in the previous sentence: it is a data storage format, cross-language, cross-platform, for communication protocols and data storage.

This looks like the JSON we are familiar with, but there are some essential differences in the focus. JSON is primarily used for data transmission because it is lightweight, readable, and simple to parse. Protobuf is mainly used for cross-language IDL, which, in addition to JSON, XML can define the structure, you can also use the self-describing format for the characteristics of the interface, and can use the protocol compiler for different languages to produce different languages of the stub class. So the natural fit in the cross-language RPC framework.

And the communication between processes, is undoubtedly the socket. The Java aspect Grpc also uses the mature open source framework Netty. Use the Netty channel as the data path. The transport protocol uses HTTP2.

Through the above analysis, we can summarize a complete GRPC process into the following steps:

    • Defines the interface and message body of the transport through the. proto file.

    • Generate server-side and client-side stub programs through the Protocol compiler.

    • Encapsulates the request into a HTTP2 stream.

    • Use a socket for data transmission via the channel as a data communication tunnel.

Four: simple implementation of code

The concept is always boring, only actual combat can really understand the problem. Below we use the code to implement a simple grpc based on the above steps. In order to embody GRPC cross-language features, this time we use two languages: Go implementation server side, Java as client side to implement.

1: Install protocol buffers, define. proto file

Sign in to Google's GitHub download for the protocol buffers version.

After the installation is complete, when we execute the PROTOC command, the following information is returned stating that the installation was successful.

Protoc

Here we define a Simple.proto file, which is the basis for the follow-up of our GRPC

syntax = "proto3"; //定义了我们使用的Protocol Buffers版本。 //表明我们定义了一个命名为Simple的服务(接口),内部有一个远程rpc方法,名字为SayHello。 //我们只要在server端实现这个接口,在实现类中书写我们的业务代码。在client端调用这个接口。 service Simple{    rpc SayHello(HelloRequest) returns (HelloReplay){} } //请求的结构体 message HelloRequest{     string name = 1; } //返回的结构体 message HelloReplay{     string message = 1; }

As you can see from the comments above, this file is a simple RPC remote method description.

2: Using Golang to achieve sever end

Use the following command to install GRPC for go according to the official documentation:

$ go get -u google.golang.org/grpc

But since we have great Great Wall, the General command will not be downloaded successfully. But Google's files generally have a mirror image on GitHub. We can use the following command:

$ go get -u github.com/grpc/grpc-go

Then rename the downloaded folder to go and put it in a new google.golang.org folder. ♀️

After we have installed GRPC and defined the details of the remote interface invocation, we will use the protocol compiler to generate our stub program.

The protocol buffers We install is used to compile our. proto files, but the compiled files cannot be used by Java, C, go, and other languages. Google has different compilers for different languages. This time we use the Golang language, so to install the compiler for Golang, according to the official command to execute:

$ go get -u github.com/golang/protobuf/protoc-gen-go

But it is possible that we will not be able to download the success, because this will rely on a lot of Golang class library, these libraries and the above installed GRPC, because of the wall, but also to perform a series of tedious steps to change the folder. But this is not our focus, we will not elaborate.

After the installation is successful, we can build the Go project.

This time we set up a Grpc-server project and then put the previously written simple.proto into the project proto package.

The following command is then executed in the project directory using the command line:

protoc -I grpc-server/ proto/simple.proto --go_out=plugins=grpc:simple

This compiles the Simple.proto into the corresponding stub program for the Go language.

Then we can write our server-side code: Main.go.

package mainimport (    "context"    "grpc-server/proto"    "fmt"    "net"    "log"    "google.golang.org/grpc"    "google.golang.org/grpc/reflection")const(    port = ":50051")type server struct{}func (s *server) SayHello(ctx context.Context,req *simple.HelloRequest) (*simple.HelloReplay, error){    fmt.Println(req.Name)    return &simple.HelloReplay{Message:"hello =======> " + req.Name},nil}func main(){    lis,err := net.Listen("tcp",port)    if err != nil {        log.Fatal("fail to listen")    }    s := grpc.NewServer()    simple.RegisterSimpleServer(s,&server{})    reflection.Register(s)    if err:= s.Serve(lis);err != nil{        log.Fatal("fail to server")    }}

The above code is the template code, the main function is the socket using go standard implementation. As a developer, we only focus on the specific interface implementations provided by the remote service.

In the end our project directory is like this:

Go-server

The simplest server-side implementation using the go language is complete.

3: Using Java to implement client side

The Java implementation is relatively simple, first we can use the familiar Maven plugin for stub code generation.

Create a new Grpc-client parent project with two sub-projects: Client and Lib. Lib is used for code generation of stub programs.

Lib Project editor Pom.xml, add Grpc for Java plug-in compiler:

<?xml version= "1.0" encoding= "UTF-8"? ><project xmlns= "http://maven.apache.org/POM/4.0.0" xmlns:xsi= "http ://www.w3.org/2001/XMLSchema-instance "xsi:schemalocation=" http://maven.apache.org/POM/4.0.0/http Maven.apache.org/xsd/maven-4.0.0.xsd "> <modelVersion>4.0.0</modelVersion> <groupid>org.js </groupId> <artifactId>grpc-client</artifactId> <version>0.0.1-SNAPSHOT</version> &    lt;packaging>pom</packaging> <modules> <module>client</module> </modules> <name>grpc-client</name> <description>demo Project for Spring boot</description> <proper Ties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reportin        G.outputencoding>utf-8</project.reporting.outputencoding> <java.version>1.8</java.version>       <grpc.version>1.13.1</grpc.version> <springboot.version>2.0.4.RELEASE</springboot.version> </properties> <dependencymanagement&        Gt                <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>${springboot.version }</version> </dependency> <dependency> <groupid>io.grpc</g Roupid> <artifactId>grpc-netty</artifactId> <version>${grpc.version}&lt ;/version> </dependency> <dependency> <groupid>io.grpc</group Id> <artifactId>grpc-protobuf</artifactId> <version>${grpc.version}< /version> </dependency> <dependency> <groupid>io.grpc</groupi           D>     <artifactId>grpc-stub</artifactId> <version>${grpc.version}</version> </dependency> <dependency> <groupid>org.springframework.boot</groupid&gt                ; <artifactId>spring-boot-starter-web</artifactId> <version>${springboot.version}</versi        on> </dependency> </dependencies> </dependencyManagement> <build>                <plugins> <plugin> <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>

Copy the defined Simple.proto file under the package proto the project. Then right-click: Run maven--compile.

Maven

After the build is complete, copy the two files from target into the client project directory.

Target

This is followed by writing our business code for GRPC remote calls. This time we write a simple Web program to simulate a remote call.

Define a class:simpleclient:

Package Org.js.client.grpc;import Io.grpc.managedchannel;import Io.grpc.managedchannelbuilder;import  java.util.concurrent.timeunit;/** * @author Jiashun * @date 2018/8/11 12:11 */public class SimpleClient {private final    Managedchannel Channel;    Private final simplegrpc.simpleblockingstub blockingstub;    Public SimpleClient (String host, int port) {This (managedchannelbuilder.foraddress (host, Port). Useplaintext ());        } private SimpleClient (managedchannelbuilder<?> channelbuilder) {channel = Channelbuilder.build ();    Blockingstub = Simplegrpc.newblockingstub (channel);    } public void Shutdown () throws interruptedexception{Channel.shutdown (). Awaittermination (5, timeunit.seconds); public string SayHello (string name) {Simpleouterclass.hellorequest req = SimpleOuterClass.HelloRequest.newBu        Ilder (). SetName (name). build ();        Simpleouterclass.helloreplay replay = Blockingstub.sayhello (req);    return Replay.getmessage (); }}

The basic is the template code. Then write a simple Web request:

Controller code:

package org.js.client.controller;import org.js.client.service.IHelloService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RestController;/** * @author JiaShun * @date 2018/8/10 22:20 */@RestControllerpublic class HelloController {    @Autowired    private IHelloService helloService;    @GetMapping("/{name}")    public String sayHello(@PathVariable String name){        return helloService.sayHello(name);    }}

Service Implementation class:

package org.js.client.service;import org.js.client.grpc.SimpleClient;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Service;/** * @author JiaShun * @date 2018/8/10 22:22 */@Servicepublic class HelloServiceImpl implements IHelloService{    private Logger logger = LoggerFactory.getLogger(HelloServiceImpl.class);    @Value("${gRPC.host}")    private String host;    @Value("${gRPC.port}")    private int port;    @Override    public String sayHello(String name) {        SimpleClient client = new SimpleClient(host,port);        String replay = client.sayHello(name);        try {            client.shutdown();        } catch (InterruptedException e) {            logger.error("channel关闭异常:err={}",e.getMessage());        }        return replay;    }}

It's so simple.

Then we test:

Start the go server side separately, Java client side.

Grpc-start

Visit: Http://localhost:8080/jiashun

Grpc-test

You can see that the server side prints out the client side request, and the client side also receives the server side return.

Full code:

Server:https://github.com/jia-shun/grpc-server

Client:https://github.com/jia-shun/grpc-client

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.