The introduction of ProtoBuffer

Google has a very efficient data transfer format framework called ProtoBuffer. Using ProtoBuffer as serialization in Java is much more efficient than the SERIalizable interface of the JDK itself (there is a sequence number performance study on Github github.com/eishay/jvm-…) This is very efficient for caching. Of course, such an excellent data format framework is not only used for caching, since compression (let’s simply understand it as compression algorithm) is so efficient, it is also much more efficient in network IO transmission than JSON or XML.

The introduction of gRPC

GRPC is an RPC framework developed by Google. The data transfer between RPC Server and RPC Clinet is the aforementioned ProtoBuffer, and the RPC framework is based on HTTP2. Therefore, HTTP2 multiplexing, stream-based transport in gRPC also has corresponding implementation.

Definition of the ProtoBuffer format

PrototBuffer official documentation: developers.google.com/protocol-bu… The author posted a format definition file in practice.

syntax = "proto3";

package vsig;

service VSIGProto {
  rpc setAcl (ACLRequest) returns (Reply) {}
  rpc openNtp  (NTPConfig) returns (Reply) {}
}
message ACLRequest {
  string extranetIp = 1;
  int32  devType = 2;
  string intranetIp = 3;
}
message InterfaceInfoRequest {
  string name =1;
  string ip = 2;
  string mask=3;
  string gateway=4;
}
message NTPInfoRequest{
  bool state = 1;
  string ntpServerIp =2;
  int32 ntpServerPort =3;
}
message NTPConfig{
  NTPInfoRequest ntpInfo = 1;
  InterfaceInfoRequest br0Info = 2;
}
message Reply {
  string message = 1;
}
Copy the code

There are three main things defined in the.proto file:

  • The method name of the RPC along with the parameters accepted and returned
  • RPC methods accept the format of arguments
  • The format returned by the RPC method

A method can only accept one argument, because I define NTPConfig to contain two more objects, ensuring that the openNtp method receives only one object

For defined messages, each value has a unique number of type number, which, according to the official documentation, is used to identify fields in message binary format and cannot be changed during use, otherwise the data will not be restored. At the same time, if the number is defined from 1 to 15, one byte is used to store the number, and 16 to 2047 requires two bytes to store the number.

The realization of gRPC Server

After defining.proto, you can use this file to use GRPC client and server. The client and server of GRPC must use the same.proto file

GRPC supports many common programming languages. The author uses Java and Node to implement gRPC.

NodeJS gRPC Server implementation

package.json:

{" name ":" GRPC - examples ", "version" : "0.1.0 from", "dependencies" : {" async ":" ^ 1.5.2, "" Google - protobuf" : "^ 3.0.0 GRPC", ""," ^ 1.0.0 ", "lodash" : "^ 4.6.1", "minimist" : "^ 1.2.0"}}Copy the code

GRPC server coding implementation:

// Const PROTO_PATH = '.. /.. /vsig.proto'; const grpc = require( 'grpc' ); // Finally vsig is the package in. Proto const proto = grpc.load(PROTO_PATH).vsig; Const rpcHost = '127.0.0.1'; const rpcPort = 50051; // Define the mapping of methods, since methods are ultimately implemented in this class, define the mapping between the modified class and methods in.proto. Const methodCover = {setAcl: setAcl, openNtp: openNtp}; Function setAcl(call, callback) {// Call. request console.log(call.request); Callback (null, {message: callback); // This callback is a callback to the client. Parameter 1 is error and parameter 2 is callback(null, {message: "rpc call setAcl method success" } ) } function openNTP( call, callback ) { const ntpInfo = call.request; console.log(ntpInfo); callback(null,{ message:"rpc call openNTP call success" }) } function main() { var server = new grpc.Server(); //VSIGProto is the name of the server in. Proto. Parameter 2 is the method mapping server.addProtoService(proto.vsigProto. service, methodCover); const grpcIn = grpc.ServerCredentials.createInsecure(); Server. bind(rpcHost + ":" + rpcPort, grpcIn); / / start server. Start (); } main();Copy the code

Implementation of Java gRPC Server

The implementation of gRPC Client

After the server is defined, it listens on the specified port, and the client only needs to send a request to the port.

Node gRPC Client implementation

const PROTO_PATH = '.. /vsig.proto'; const grpc = require( 'grpc' ); // Finally vsig is the package in. Proto const proto = grpc.load(PROTO_PATH).vsig; Const rpcHost = '127.0.0.1; const rpcPort = 50051; //VSIGProto is a const client = new proto.VSIGProto(rpcHost + ":" + rpcPort, grpc.credentials.createInsecure() ); Class RpcClient {setAcl(acl, cb) {// Execute RPC call client.setacl (acl, function(err, response) {cb(err, response)});  OpenNTP (ntpconfig, function(err, response) {cb(err, response); response ); }); } } const rpcClient = new RpcClient(); module.exports = rpcClient;Copy the code

Java gRPC Client implementation