一.安装
安装protoc
首先要装protoc命令,因为需要编辑一个.proto文件,所以grpc需要使用 Protocol Buffers 编译器生成代码,使用 Protocol Buffers 编译器将 .proto
文件编译为 Node.js 代码。
这里感觉并不需要用命令行编译,直接下载 .exe文件。https://github.com/protocolbuffers/protobuf/releases
Windows10环境下,点击下载这个zip。
解压后是这样的
双击进入bin文件夹,会有一个protoc.exe文件
将路径复制到环境变量的系统变量PATH中
protoc安装完毕,可以到cmd中输入 protoc --version 验证一下
protoc --version
二.使用
grpc中文版官方文档:Quick start | Node | gRPC
grpc官方文档:Quick start | Node | gRPC
可以直接去官网下载实例
git clone -b @grpc/grpc-js@1.9.0 --depth 1 --shallow-submodules https://github.com/grpc/grpc-node
代码
我这边是直接新建文件夹也就是node.js项目在里面新建了三个文件, client.js、server.js、helloworld.proto
在项目中安装grpc/grpc-js模块,后续代码中会用 require 语句来导入 @grpc/grpc-js
模块
npm install @grpc/grpc-js
helloworld.proto 就是需要使用 Protocol Buffers 编译器也就是前面下载的将 .proto
文件编译为 Node.js 代码的文件。
helloworld.proto代码
syntax = "proto3";
package helloworld;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
server.js代码
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const path = require('path');
const PROTO_PATH = path.join(__dirname, 'helloworld.proto'); // 使用 path.join() 获取文件路径
const packageDefinition = protoLoader.loadSync(PROTO_PATH);
const hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;
const server = new grpc.Server();
server.addService(hello_proto.Greeter.service, {
sayHello: function(call, callback) {
callback(null, {message: 'Hello我是第一个服务器 ' + call.request.name});
}
});
server.bindAsync('localhost:50051', grpc.ServerCredentials.createInsecure(), (err, port) => {
if (err) {
console.error(err);
return;
}
console.log(`Server listening on ${port}`);
server.start();
});
client.js代码
//基本的向服务端发送请求
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
// 加载 .proto 文件
const packageDefinition = protoLoader.loadSync('helloworld.proto', {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
const hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;
// 创建 gRPC 客户端
const client = new hello_proto.Greeter('localhost:50051', grpc.credentials.createInsecure());
// 向服务器发送请求
client.sayHello({ name: '请求' }, (error, response) => {
if (!error) {
for(let i = 0; i < 1000; i++){
console.log('Greeting:', `${response.message} ${i} 次`);
}
} else {
console.error('Error:', error);
}
});
// const grpc = require('@grpc/grpc-js');
// const protoLoader = require('@grpc/proto-loader');
//多线程请求
// const { Worker, isMainThread, parentPort } = require('worker_threads');
// const grpc = require('@grpc/grpc-js');
// const protoLoader = require('@grpc/proto-loader');
// //使用 worker_threads 模块在 Node.js 中使用多线程,这个模块提供了创建和管理多个线程的功能。可以使用 Worker 类创建一个新的工作线程,并在其中执行代码。工作线程之间可以通过消息传递进行通信。
// // 判断当前是否在主线程中运行
// if (isMainThread) {
// const workerCount = 300; // 创建 4 个 Worker
// const workers = []; // 存储 Worker 对象
// // 创建 Worker
// for (let i = 0; i < workerCount; i++) {
// const worker = new Worker(__filename);
// workers.push(worker);
// }
// // 向所有 Worker 发送请求
// workers.forEach((worker) => {
// worker.postMessage({ message: '请求' });
// });
// // 监听 Worker 的响应
// workers.forEach((worker,index) => {
// worker.on('message', (message) => {
// console.log(message,`第${index}次`); // 打印响应结果
// });
// });
// } else {
// // 加载 .proto 文件
// const packageDefinition = protoLoader.loadSync('helloworld.proto', {
// keepCase: true,
// longs: String,
// enums: String,
// defaults: true,
// oneofs: true
// });
// const hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;
// // 创建 gRPC 客户端
// const client = new hello_proto.Greeter('localhost:50051', grpc.credentials.createInsecure());
// // 监听主线程发送的请求
// parentPort.on('message', (message) => {
// // 向服务器发送请求
// client.sayHello({ name: message.message }, (error, response) => {
// if (!error) {
// parentPort.postMessage(response); // 将响应结果发送给主线程
// } else {
// console.error('Error:', error);
// }
// });
// });
// }
//客户端-两个工作线程之间的通信
// const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');
// if (isMainThread) {
// const worker1 = new Worker(__filename, { workerData: 'Worker1' });
// const worker2 = new Worker(__filename, { workerData: 'Worker2' });
// // 向 Worker1 发送消息
// worker1.postMessage({ message: 'Hello,你是一吗' });
// // 监听从 Worker1 收到的消息
// worker1.on('message', (message) => {
// console.log('我是第一个线程:', message);
// // 向 Worker2 发送消息
// worker2.postMessage({ message: 'Hello,你是二吗' });
// });
// // 监听从 Worker2 收到的消息
// worker2.on('message', (message) => {
// console.log('我是第二个线程:', message);
// });
// } else {
// // 监听从主线程收到的消息
// parentPort.on('message', (message) => {
// console.log(`接收主线程的消息,问 ${workerData}:`, message);
// // 向主线程发送消息
// parentPort.postMessage({ message: `from ${workerData}` });
// });
// }
最后开两个终端,分别执行 node server.js 和 node client.js命令
node server.js
node client.js