如何在 NodeJS 中實現(xiàn) gRPC 服務?

言鼎科技 2023-06-21 393

什么是 gRPC?

gRPC:谷歌遠程過程調(diào)用是谷歌開發(fā)的開源框架。gRPC 允許您為遠程過程調(diào)用定義請求和響應,并通過處理其余部分來減少您的努力。gRPC 的特點:

  • 現(xiàn)代的

  • 快速地

  • 具有低延遲

  • 高效負載均衡

  • 支持串流

  • 插件認證

  • 監(jiān)控數(shù)據(jù)

  • 建立在 HTTP/2 之上

  • 語言無關

教程目標:在 NodeJS 中實現(xiàn) gRPC 服務

我們都知道 NodeJs 有多流行和成功。因此,在本教程中,我們將在 NodeJs 中實現(xiàn) gRPC 服務。我們將構建一個演示應用程序并執(zhí)行 CRUD 操作。因此,事不宜遲,讓我們開始在我們的 NodeJS 應用程序中實現(xiàn) gRPC 服務。

Bacancy 將減少您的開發(fā)困難。相信最好的!相信我們!
如果您正在為您的夢想項目尋找潛在的 NodeJS 開發(fā)人員,請聯(lián)系 Bacancy。我們擁有技術精湛的開發(fā)人員,他們擁有出色的問題解決方法。別想太多!只需聯(lián)系我們并從我們這里聘請 NodeJs 開發(fā)人員!

在 NodeJS 中實現(xiàn) gRPC 服務的步驟

初始化節(jié)點環(huán)境

如何在 NodeJS 中實現(xiàn) gRPC 服務?
npm 初始化 -y

安裝 gRPC 服務器

如何在 NodeJS 中實現(xiàn) gRPC 服務?
npm install --save grpc @grpc/proto-loader uuid express body-parser

grpc:它將安裝 gRPC 服務器
/proto-loader:它將加載 protobuf 文件
uuid:它將為學生創(chuàng)建隨機哈希 ID

現(xiàn)在,創(chuàng)建students.proto、server.jsclient.js文件。單個學生項目將具有 - id、name、age 和 coursename。

如何在 NodeJS 中實現(xiàn) gRPC 服務?
語法=“proto3”;消息學生{
   字符串 ID = 1;
   字符串名稱 = 2;
   int32 年齡 = 3;
   字符串課程名稱 = 4;}

Students 定義了我們的學生請求消息格式,其中每個消息請求都有一個唯一的id、學生的姓名、學生的年齡以及學生選擇的課程名稱。

在 proto 中定義 StudentService

創(chuàng)建 RPC 服務。所有 CRUD 操作都將在名為 StudentsService 的服務中可用。

如何在 NodeJS 中實現(xiàn) gRPC 服務?
...服務學生服務{(diào)
   rpc GetAllStudents (Empty) 返回 (NewsList) {}}消息空{(diào)}留言學生名單{
  重復學生 students = 1;}

news.proto文件的全部代碼如下所示。

如何在 NodeJS 中實現(xiàn) gRPC 服務?
語法=“proto3”;服務學生服務{(diào)
   rpc GetAllNews (Empty) 返回 (NewsList) {}}消息學生{
   字符串 ID = 1;
   字符串名稱 = 2;
   int32 年齡 = 3;
   字符串課程名稱 = 4;}消息空{(diào)}留言學生名單{
  重復學生 students = 1;}const grpc = require("@grpc/grpc-js");const PROTO_PATH = "./news.proto";var protoLoader = require("@grpc/proto-loader");常量選項 = {
 多頭:字符串,
 一個:真實的,
 保持大小寫:真實,
 枚舉:字符串,
 默認值:真,};var packageDefinition =protoLoader.loadSync(PROTO_PATH, options);const newsProto=grpc.loadPackageDefinition(packageDefinition);const {v4:uuidv4}=require(“uuid”)const server = new grpc.Server();讓學生們= [
 {編號:“a68b823c-7ca6-44bc-b721-fb4d5312cafc”,名稱:“約翰·博爾頓”,年齡:22歲,課程名稱:“課程1”
 },
 {編號:“34415c7c-f82d-4e44-88ca-ae2a1aaa92b7”,名稱:“約翰·博爾頓”,年齡:22歲,課程名稱:“課程2”
 },  ];server.addService(StudentsProto.StudentService.service, {
 getAll: (_, 回調(diào)) => {
   回調(diào)(空,{學生});
 },});server.bind("127.0.0.1:30043",grpc.ServerCredentials.createInsecure());console.log("服務器運行在 http://127.0.0.1:50051");服務器.start();

首先,我們導入了@grpc/grpc-js@grpc/proto-loader庫。名為PROTO PATH 的常量變量將保存students.proto文件的位置。稍后,loadSync 方法會將 proto 文件加載到 gRPC 中。loadPackageDefinition方法加載包定義。之后,為了初始化服務器實例(),我們將調(diào)用 new grpc.server

創(chuàng)建客戶端存根

我們將調(diào)用 Server 的 addService 方法中定義的 getAll 方法作為客戶端的第二個參數(shù),如下所示。

如何在 NodeJS 中實現(xiàn) gRPC 服務?
const PROTO_PATH = "./students.proto";const grpc = require("@grpc/grpc-js");var protoLoader = require("@grpc/proto-loader");var packageDefinition=protoLoader.loadSync(PROTO_PATH, {
 多頭:字符串,
 一個:真實的,
 保持大小寫:真實,
 枚舉:字符串,
 默認值:真,});const StudentService = grpc.loadPackageDefinition(packageDefinition).StudentService;const client = new StudentService(
 “本地主機:30043”,
 grpc.credentials.createInsecure());

getAll 方法:獲取所有學生

從客戶端變量調(diào)用服務器中的 getAll 方法。

如何在 NodeJS 中實現(xiàn) gRPC 服務?
...const 客戶端 = 新服務(
 “本地主機:30043”,
 grpc.credentials.createInsecure());client.getAll(null, (err, data) => {
 如果 (!err) 拋出錯誤
   控制臺日志(數(shù)據(jù));});

現(xiàn)在執(zhí)行 client.js 代碼如下:

如何在 NodeJS 中實現(xiàn) gRPC 服務?
// 節(jié)點客戶端.js{
 學生: [
   {編號:“a68b823c-7ca6-44bc-b721-fb4d5312cafc”,名稱:“約翰·博爾頓”,年齡:22歲,課程名稱:“課程1”
 },
 {編號:“34415c7c-f82d-4e44-88ca-ae2a1aaa92b7”,名稱:“約翰·博爾頓”,年齡:22歲,課程名稱:“課程2”
 },
]}

我們已經(jīng)從 gRPC 客戶端成功執(zhí)行了 gRPC 服務方法。導出 NewsService 實例后,您可以將其導入另一個文件以調(diào)用方法。

如何在 NodeJS 中實現(xiàn) gRPC 服務?
const PROTO_PATH = "./students.proto";const grpc = require("@grpc/grpc-js");var protoLoader = require("@grpc/proto-loader");var packageDefinition=protoLoader.loadSync(PROTO_PATH, {
 多頭:字符串,
 一個:真實的,
 保持大小寫:真實,
 枚舉:字符串,
 默認值:真,});const StudentService = grpc.loadPackageDefinition(packageDefinition).StudentService;const client = new StudentService(
 “本地主機:30043”,
 grpc.credentials.createInsecure());module.exports = 客戶端;

我們現(xiàn)在可以將客戶端導入到不同的文件中。我們將為我們希望采取的每個步驟制作一個單獨的文件。我們將創(chuàng)建一個名為 get test.js 的文件,該文件導入客戶端并調(diào)用 getAll 方法。

如何在 NodeJS 中實現(xiàn) gRPC 服務?
// 測試.jsconst client = require("./client");client.getAll(null, (err, data) => {
 如果 (!err) 拋出錯誤
   控制臺日志(數(shù)據(jù));});

插入學生記錄

為插入數(shù)據(jù)創(chuàng)建一個新方法。打開 proto 文件并在服務下,您可以添加一個帶有新方法名稱的 RPC。在這里,我們的方法名稱是 Insert under StudentService 服務,如下所示。

如何在 NodeJS 中實現(xiàn) gRPC 服務?
...服務學生服務{(diào)
   rpc GetAll(空)返回(StudentList){}
   rpc 插入(學生)返回(學生){}}...

該服務將接受 Student 消息并返回新的 Student 對象。

如何在 NodeJS 中實現(xiàn) gRPC 服務?
...server.addService(StudentsProto.StudentService.service, {
 getAll: (_, 回調(diào)) => {
   回調(diào)(空,{學生});
 },
 插入:(調(diào)用,回調(diào))=> {
   讓 Student = call.request;
   Student.id = uuidv4();
   Students.push(學生);
   回調(diào)(空,新聞);
 },});...

刪除學生

現(xiàn)在,我們將編寫刪除學生的代碼。這是相同的代碼片段。

如何在 NodeJS 中實現(xiàn) gRPC 服務?
...服務學生服務{(diào)
   rpc GetAll(空)返回(StudentList){}
   rpc 插入(學生)返回(學生){}
   rpc 刪除(學生)返回(學生){}}消息 StudentRequestId {
   字符串 ID = 1;}...

在這里,請求是StudentRequestId,它將返回一條空消息。

來自 server.js 的代碼片段如下所示。

如何在 NodeJS 中實現(xiàn) gRPC 服務?
...
 刪除:(調(diào)用,回調(diào))=> {
   讓 existingStudentIndex = Students.findnidex(
n =>n.id == call.request.id);如果(現(xiàn)有學生索引!= -1){
Students.splice(existingStudentIndex,1)
回調(diào)(空,{});
   }},...

更新現(xiàn)有學生

為了更新數(shù)據(jù),我們將在原型文件中添加一個方法。

如何在 NodeJS 中實現(xiàn) gRPC 服務?
...服務學生服務{(diào)
   rpc GetAll(空)返回(StudentList){}
   rpc 插入(學生)返回(學生){}
   rpc 刪除(學生)返回(學生){}
   rpc 更新(學生)返回(學生){}}...

該方法接受 Student 消息并使用編輯后的 News 對象進行響應。更新學生數(shù)據(jù)的代碼如下所示。

如何在 NodeJS 中實現(xiàn) gRPC 服務?
...
 更新:(調(diào)用,回調(diào))=> {
   讓 existingStudent = Students.find(n=> n.id== call.request.id);
如果(現(xiàn)有學生){
existingStudent.name = call.request.name;
existingStudent.age = call.request.age;
existingStudent.CourseName =call.request.CourseName;
回調(diào)(空,現(xiàn)有學生);},...

得到一個學生

讓我們在 proto 文件中設置一個方法:

如何在 NodeJS 中實現(xiàn) gRPC 服務?
...服務學生服務{(diào)
   rpc GetAll(空)返回(StudentList){}
   rpc 獲?。▽W生)返回(學生){}
   rpc 插入(學生)返回(學生){}
   rpc 刪除(學生)返回(學生){}
   rpc 更新(學生)返回(學生){}}...

Get 方法需要 ID 作為請求消息并返回 Student 消息。這是 server.js 文件中的實現(xiàn):

如何在 NodeJS 中實現(xiàn) gRPC 服務?
...
 得到:(調(diào)用,回調(diào))=> {
   讓 Student = Students.find(n=>n.id == call.request.id)
   如果(學生)= {
   回調(diào)(空,學生);}
 },...

我們從調(diào)用參數(shù)對象中獲取 id。id 用于從 Students 數(shù)組中檢索相應的學生項目。使用作為參數(shù)傳遞的檢索到的學生項目調(diào)用回調(diào)函數(shù),這使得客戶端獲取學生項目。

如何在 NodeJS 中實現(xiàn) gRPC 服務?
// 測試.js// 獲取所有消息const client = require("./client");client.getAll({}, (error, students) => {
 如果(錯誤)拋出錯誤;
 控制臺日志(學生);});//添加一個學生客戶.插入(
 {
   name: "標題新聞3",
   年齡:11歲,
   CourseName: "這里是圖片地址",
 },
 (錯誤,學生)=> {
   如果(錯誤)拋出錯誤;
   console.log("成功創(chuàng)建學生。");
 });// 編輯學生客戶端.更新(
 {
   編號:“a68b823c-7ca6-44bc-b721-fb4d5312cafc”,
   name: "標題新聞3",
   年齡:11歲,
   CourseName: "這里是圖片地址",
 },
 (錯誤,學生)=> {
   如果(錯誤)拋出錯誤;
   console.log("成功更新一個學生。");
 });//刪除一個學生客戶.刪除(
 {
   編號:“34415c7c-f82d-4e44-88ca-ae2a1aaa92b7”,
 },
 (錯誤,學生)=> {
   如果(錯誤)拋出錯誤;
   console.log("成功刪除學生記錄。");
 });

現(xiàn)在,運行文件:

如何在 NodeJS 中實現(xiàn) gRPC 服務?
節(jié)點測試

使用 Http 服務器

我們現(xiàn)在已經(jīng)構建并準備好了服務器、原型和客戶端。將 Node 服務器附加到 client.js,以便我們服務器中的端點將調(diào)用gRPC新聞服務中的過程。這是端點。

  • /GET 端點將調(diào)用 getAll 子例程以獲取數(shù)據(jù)庫中的所有學生。

  • /save POST 端點將調(diào)用插入子例程來創(chuàng)建新的學生項目。

  • /update PUT 將調(diào)用更新子例程來編輯/更新學生項目。

  • /remove DELETE 將調(diào)用刪除子例程來刪除學生項目。

這是 Nodejs 中的代碼:

如何在 NodeJS 中實現(xiàn) gRPC 服務?
const client = require("./client");const express = require("快遞");const bodyParser = require("body-parser");const app = express();app.use(bodyParser.json());app.use(bodyParser.urlencoded({ extended: false }));app.get("/", (req, res) => {
client.getAll(null, (err, data) => {
如果(!錯誤){
重新發(fā)送(數(shù)據(jù)。學生)
}
});});app.post("/保存", (req, res) => {
console.log(req.body.CourseName)
讓新學生={
名稱:req.body.name,
年齡:req.body.age,
課程名稱:req.body.CourseName
};
client.insert(newStudent, (err, data) => {
如果(錯誤)拋出錯誤;res.send({data:data, msg:"學生創(chuàng)建成功"})
});});app.post("/update", (req, res) => {
const updateStudent = {
id: req.body.id,
名稱:req.body.name,
年齡:req.body.age,
課程名稱:req.body.CourseName
};
client.update(updateStudent, (err, data) => {
如果(錯誤)拋出錯誤;
res.send({msg:"學生更新成功"})
});});app.post("/remove", (req, res) => {
client.remove({ id: req.body.Student_id }, (err, _) => {
如果(錯誤)拋出錯誤;
console.log("學生刪除成功");
//res.redirect("/");
res.send({msg:"學生刪除成功"})
});});常量端口 = 3000;app.listen(PORT, () => {
console.log("服務器運行在端口 %d", PORT);});

結論

所以,這是關于我們?nèi)绾卧?NodeJS 中實現(xiàn) gRPC 服務。我希望您閱讀本教程的目的對您有所幫助。如果您是 NodeJS 愛好者,請隨時訪問NodeJS 教程頁面并了解有關 Node.js 的更多信息。我們始終樂于接受建議和反饋。如果您有任何問題,請給我們回信。Bacancy 擁有擁有基礎和高級知識的最佳 NodeJS 開發(fā)人員;聯(lián)系我們?yōu)槟膽贸绦蚱刚?NodeJs 開發(fā)人員。

言鼎科技主做軟件開發(fā),微信小程序,網(wǎng)站開發(fā),軟件外包,手機APP開發(fā)。如有需要記得聯(lián)系我們!

The End