gRPC Node

gRPC Node

Shopee qps Node Node

Shopee gRPC Node

gRPC

gRPC

What is gRPC

gRPC is a modern, open source remote procedure call (RPC) framework that can run anywhere. It enables client and server applications to communicate transparently, and makes it easier to build connected systems.

Read the longer Motivation & Design Principles post for background on why we created gRPC.

gRPC Google rpc HTTP2 Protocol Buffers Google rpc

What is protobuf

hello.pb

//The greeter service definition. service Greeter { //Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply) {} } //The request message containing the user's name. message HelloRequest { string name = 1; } //The response message containing the greetings message HelloReply { string message = 1; }

gRPC protobuf protobuf service message messgae protobuf grpc server client

server & client

node-grpc node gRPC

protobuf protobuf server routeguide server

var PROTO_PATH = __dirname + '/../../../protos/hello.proto'; var grpc = require('@grpc/grpc-js'); var protoLoader = require('@grpc/proto-loader'); //Suggested options for similarity to existing grpc.load behavior var packageDefinition = protoLoader.loadSync( PROTO_PATH, {keepCase: true, longs: String, enums: String, defaults: true, oneofs: true }); var protoDescriptor = grpc.loadPackageDefinition(packageDefinition); //The protoDescriptor object has the full package hierarchy var helloObj = protoDescriptor.hello;
helloObj gRPC server protobuf
import grpc from "@grpc/grpc-js"; // //https://grpc.io/docs/languages/node/basics/ // call callback metedata =>{} // function sayHello(call,callback) { //do something callback(); } function getServer() { var server = new grpc.Server(); server.addService(helloObj.Greeter.service, { sayHello: sayHello, }); return server; } var greeterServer = getServer(); greeterServer.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => { routeServer.start(); });
helloObj gRPC

var client = new helloObj.Greeter('localhost:50051', grpc.credentials.createInsecure()); function sayHello(callback) { const helloReq = { name: "you" }; var call = client.sayHello(name, function(err, response) { console.log('Greeting:', response.message); }); }

grpc-tools

_pb.d.ts
_grpc_pb.d.ts
protobuf message enum client server
hello_pb.d.ts
hello_grpc_pb.d.ts

ts ts

//hello_pb.d.ts HelloRequest import * as jspb from "google-protobuf"; export class HelloRequest extends jspb.Message { getName(): string; setName(value: number): HelloRequest; serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): HelloRequest.AsObject; static toObject(includeInstance: boolean, msg: Book): HelloRequest.AsObject; } export namespace HelloRequest { export type AsObject = { name: string, }

hello_grpc_pb.d.ts
GreeterClient
address client server uds dns etcd resolver etcd

//hello_grpc_pb.d.ts import * as hello_pb from "./hello_pb"; import * as grpc from "@grpc/grpc-js"; interface IGreeterService extends grpc.ServiceDefinition<grpc.UntypedServiceImplementation> { sayHello: IGreeterServiceService_ISayHello; } export const GreeterService: IGreeterService; export class GreeterClient extends grpc.Client { constructor(address: string, credentials: grpc.ChannelCredentials, options?: object); sayHello( argument: helloworld_pb.HelloRequest, callback: grpc.requestCallback<helloworld_pb.HelloReply> ): grpc.ClientUnaryCall; sayHello( argument: helloworld_pb.HelloRequest, metadataOrOptions: grpc.Metadata | grpc.CallOptions | null, callback: grpc.requestCallback<helloworld_pb.HelloReply> ): grpc.ClientUnaryCall; sayHello( argument: helloworld_pb.HelloRequest, metadata: grpc.Metadata | null, options: grpc.CallOptions | null, callback: grpc.requestCallback<helloworld_pb.HelloReply> ): grpc.ClientUnaryCall; }
import {GreeterService, IGreeterService} from "./proto/hello_grpc_pb"; function sayHello(call,callback,metedata){ //do something callback(); } function main() { var server = new grpc.Server(); server.addService(GreeterService, {sayHello: sayHello}); server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => { server.start(); }); }
Client
import { GreeterClient } from "./proto/hello_grpc_pb"; import { HelloRequest, HelloReply } from "./proto/hello_pb"; const client = new GreeterClient("127.0.0.1:50051", grpc.credentials.createInsecure()); const helloRequest = new HelloRequest(); helloRequest.setName('hello world!') // client.sayHello(request, (err, reply: HelloReply) => { if (err != null) { debug(`[sayHello] err:\nerr.message: ${err.message}\nerr.stack:\n${err.stack}`); reject(err); return; } log(`[sayHello] HelloReply: ${JSON.stringify(reply.toObject())}`); resolve(book); });

rpc

gRPC sayHello

HelloRequest json HelloRequest

Why use gRPC?

ShopeePay node node shopee node gRPC http koa express

node http gRPC gRPC

grpc node go node http http go node http grpc http gRPC

http http hack

gRPC

ShopeePay Kubernetes ingress pod ingress node

  • node

http nginx ingress

gRPC trace-id metadata metedata gRPC header http http

gRPC node protobuf.js node gRPC gRPC json manager

pb pb gRPC gRPC pb

json go json go pb struct json go json

call protobuf message CommonMessage CommonMessage CommonMessage messgae

CommonMessage pb

//The request message containing the common content. message CommonMessage { byte content = 1; }

grpc vs grpc-js

grpc-node node grpc c grpc js grpc-js grpc grpc github.com/grpc/grpc-n

grpc http2 grpc-js 300KB grpc 10002000ms grpc-js 2030ms github.com/grpc/grpc-n

callback grpc-jsgrpc
5KB1~10ms1~10ms
500KB1~10ms1000ms~2000ms

callback

//grpc /** * Send a response to a unary or client streaming call. * @private * @param {grpc.Call} call The call to respond on * @param {*} value The value to respond with * @param {grpc~serialize} serialize Serialization function for the * response * @param {grpc.Metadata=} metadata Optional trailing metadata to send with * status * @param {number=} [flags=0] Flags for modifying how the message is sent. */ function sendUnaryResponse(call, value, serialize, metadata, flags) { //a var end_batch = {}; var statusMetadata = new Metadata(); var status = { code: constants.status.OK, details: 'OK' }; if (metadata) { statusMetadata = metadata; } var message; try { message = serialize(value); } catch (e) { common.log(constants.logVerbosity.ERROR, e); e.code = constants.status.INTERNAL; handleError(call, e); return; } status.metadata = statusMetadata._getCoreRepresentation(); if (!call.metadataSent) { end_batch[grpc.opType.SEND_INITIAL_METADATA] = (new Metadata())._getCoreRepresentation(); call.metadataSent = true; } message.grpcWriteFlags = flags; end_batch[grpc.opType.SEND_MESSAGE] = message; end_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = status; // //b call.startBatch(end_batch, function (){}); // //c }

grpc a-b messge metadata b-c http2 a-b 1~2ms b-c startBatch c grpc-js grpc deprecated

.

gRPC node GitHub issue node go grpc fork node-grpc-interceptors ctx response errorcallback grpc worker

20 4 @grpc/grpc-js 1.0.0 grpc-js Resolver etcd Resolver proto-tools grpc-js plugin plugin ts

Protobuff

Protobuff ShopeePay protobuff static proto client

ShopeePay protobuff node gRPC gRPC proto proto

grpc-js json json to protobuff message client etcd resolver Kubernetes pod ip

  • protobuff node_modules pb
  • set pb
  • pb pb n n pb Protobuff pb
  • ...

gRPC hello world ShopeePay gRPC cover

ShopeePay gRPC BrandonXiang HeyLi Shopee _