1.1 RPC 框架原理
RPC 框架的目标就是让远程服务调用更加简单、透明,RPC 框架的目标就是让远程服务调用更加简单、透明,RPC 框架负责屏蔽底层的传输方式(TCP 或者 UDP)、序列化方式(XML/Json/ 二进制)和通信细节。服务调用者可以像调用本地接口一样调用远程的服务提供者,而不需要关心底层通信细节和调用过程。
原理流程如下:
2.gRPC
gRPC 是由 Google 开发并开源的一种语言中立的 RPC 框架,当前支持 C、Java 和 Go 语言,其中 C 版本支持 C、C++、Node.js、C# 等。
2.1. gRPC 服务端创建
下面以搭建一个node服务为例介绍gRPC的使用(windows环境):
首先安装node.js(安装地址:https://nodejs.org/en/download/)
2.1.1在任意磁盘下建立文件夹rgpc-node,命令提示符敲:npm init 建立项目
2.1.2安装protoc以及grpc插件
这个用npm直接安装
npm install grpc-tools --save-dev
npm install google-protobuf --save
npm install grpc --save
在./node_modules/grpc-tools/bin下,你会找到 protoc.exe 和 grpc_node_plugin.exe两个文件。
如果在npm install grpc-tools --save-dev 安装时node-pre-spy 安装不成功是,下面会有 package.json文件附上,把package.json里的依赖拷进到你的依赖里去,npm install 即可,安装 以上工具的目的是我们要使用.proto文件并使用protoc 进行编译
package.json
{
"name": "grpc-node",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@grpc/proto-loader": "^0.1.0",
"async": "^1.5.2",
"google-protobuf": "^3.0.0",
"grpc": "^1.11.0",
"lodash": "^4.6.1",
"minimist": "^1.2.0"
}
}
以上都安装好了,开始创建一个 HelloWorldService.proto文件
syntax = "proto3";
option java_package = "ex.grpc";
option objc_class_prefix = "HSW";
package hellostreamingworld;
// The greeting service definition.
service MultiGreeter {
// Sends multiple greetings
rpc sayHello (HelloRequest) returns (stream HelloReply) {}
}
// The request message containing the user's name and how many greetings
// they want.
message HelloRequest {
string name = 1;
string num_greetings = 2;
}
// A response message containing a greeting
message HelloReply {
string message = 1;
}
运行编译命令
./node_modules/grpc-tools/bin/protoc --js_out=import_style=commonjs,binary:./ --plugin=protoc-gen-grpc=./node_modules/grpc-tools/bin/grpc_node_plugin.exe --grpc_out=./ HelloWorldService.proto
运行完成后,会生成HelloWorldService_grpc_pb.js 和 HelloWorldServer_pb.js两个文件。(这一步要不要无关大局,只是将.proto文件转成相应的.js文件,.proto文件一样可以引入)
如果是你使用了编译命令生成了两个相应的.js文件
下面建立server.js文件(前提是你编译成功)
var services = require('./HelloWorldService_grpc_pb.js');
var messages = require('./HelloWorldService_pb.js');
var grpc = require('grpc')
var hello = function(call, callback) {
var response = new messages.HelloResponse();
response.setHellostring("hello," + call.request.getName());
callback(null, response);
}
var server = new grpc.Server();
server.addService(
services.HelloWorldServiceService,
{
hello:hello
}
);
server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
server.start(function(err,data){
console.log(err);
console.log(data);
});
紧接着是建立client.js文件(前提是你编译成功)
var grpc = require('grpc');
var messages = require('./HelloWorldService_pb.js');
var services = require('./HelloWorldService_grpc_pb.js')
var request = new messages.HelloRequest();
request.setName('world');
var client = new services.HelloWorldServiceClient(
'localhost:50051',
grpc.credentials.createInsecure()
);
client.hello(request, function(err,data){
if(err){
console.error(err);
}
console.log(data);
console.log(data.getHellostring());
})
倘若没有将.proto文件编译成相应的.js文件
Node.js 的类库在运行时加载 .proto
中的客户端存根并动态生成服务描述符。
要加载一个 .proto
文件,只需要 require
gRPC 类库,然后使用它的 load()
方法:
步骤同上
1建立server.js文件
var PROTO_PATH = __dirname + '/../../protos/helloworld.proto';
var grpc = require('grpc');
var protoLoader = require('@grpc/proto-loader');
var packageDefinition = protoLoader.loadSync(
PROTO_PATH,
{keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
var hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;
/**
* Implements the SayHello RPC method.
*/
function sayHello(call, callback) {
callback(null, {message: 'Hello ' + call.request.name});
}
/**
* Starts an RPC server that receives requests for the Greeter service at the
* sample server port
*/
function main() {
var server = new grpc.Server();
server.addService(hello_proto.Greeter.service, {sayHello: sayHello});
server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
server.start();
}
main();
建立client.js文件
var PROTO_PATH = __dirname + '/../../protos/helloworld.proto';
var grpc = require('grpc');
var protoLoader = require('@grpc/proto-loader');
var packageDefinition = protoLoader.loadSync(
PROTO_PATH,
{keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
var hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;
function main() {
var client = new hello_proto.Greeter('localhost:50051',
grpc.credentials.createInsecure());
var user;
if (process.argv.length >= 3) {
user = process.argv[2];
} else {
user = 'world';
}
client.sayHello({name: user}, function(err, response) {
console.log('Greeting:', response.message);
});
}
main();
接着就是怎么运行了,首先在你的项目根目录cmd 直接运行node server.js
接着仍然是那个根目录cmd 直接运行node client.js 你会看到打印出Greeting: hello world