What exactly is gRPC?
Google Remote Procedure Call (gRPC) is an open-source framework developed by Google. The gRPC allows you to define REQUEST AND RESPONSE for Remote Procedure Calls and handles the rest for you. gRPC has the following features:
Modern
Fast
Has a short latency
Load balancing that works
Streaming is supported.
Authentication of plugins
Data is being monitored.
Built on the HTTP/2 protocol
Independent of the language
The goal of this tutorial is to show you how to use NodeJS to implement gRPC services.
We’re all aware of NodeJs’ popularity and success. As a result, we’ll implement gRPC services in NodeJs in this tutorial. We’ll create an example application and run a CRUD operation on it. Let’s get started with the implementation of gRPC services in our NodeJS application without further ado.
IndyLogix will make your development process easier. Put your faith in the best! Have faith in us!
If you’re looking to hire dedicated Node.JS developer for your ideal project, get in touch with IndyLogix. We have a team of highly skilled developers who have excellent problem-solving skills. Don’t overthink it! Simply contact us to hire a NodeJs developer!
How to Set Up gRPC Services in NodeJS
Set up the environment for the node
npm init -y
npm install –save grpc @grpc/proto-loader uuid express body-parser
grpc: It will install the gRPC server
/proto-loader: It will load protobuf file
uuid: It will create random hash ids for students
Create files for students.proto, server.js, and client.js now. ID, name, age, and coursename will all be included in a single student item.
syntax = “proto3”;
message Student {
string id = 1;
string name = 2;
int32 age = 3;
string CourseName = 4;
}
Our students request message format is defined by the students, and each news request has a unique id, as well as the students’ names, ages, and course names.
Create a prototype for the StudentService.
Create a remote procedure call (RPC) service. This service, called StudentsService, will support all CRUD activities.
…
service StudentsService {
rpc GetAllStudents (Empty) returns (NewsList) {}
}
message Empty {}
message StudentsList {
repeated Students students = 1;
}
Below is the whole code for the news.proto file.
syntax = “proto3”;
service StudentService {
rpc GetAllNews (Empty) returns (NewsList) {}
}
message Student {
string id = 1;
string name = 2;
int32 age = 3;
string CourseName = 4;
}
message Empty {}
message StudentsList {
repeated Student students = 1;
}
const grpc = require(“@grpc/grpc-js”);
const PROTO_PATH = “./news.proto”;
var protoLoader = require(“@grpc/proto-loader”);
const options = {
longs: String,
oneofs: true,
keepCase: true,
enums: String,
defaults: true,
};
var packageDefinition =protoLoader.loadSync(PROTO_PATH, options);
const newsProto=grpc.loadPackageDefinition(packageDefinition);
const {v4:uuidv4}=require(“uuid”)
const server = new grpc.Server();
let Students = [
{
id: “a68b823c-7ca6-44bc-b721-fb4d5312cafc”,
name: “John Bolton”,
age: 22,
courseName: “Course 1”
},
{
id: “34415c7c-f82d-4e44-88ca-ae2a1aaa92b7”,
name: “John Bolton”,
age: 22,
courseName: “Course 2”
},
];
server.addService(StudentsProto.StudentService.service, {
getAll: (_, callback) => {
callback(null, {Students});
},
});
server.bind(“127.0.0.1:30043”,grpc.ServerCredentials.createInsecure());
console.log(“Server running at http://127.0.0.1:50051”);
server.start();
First and foremost, the @grpc/grpc-js and @grpc/proto-loader libraries have been loaded. PROTO PATH is a const variable that saves the location of the students.proto file. The proto file will then be loaded into gRPC using the loadSync function. The package definition will be loaded using the loadPackageDefinition method. After that, we’ll use new grpc.server to start the server instance ().
Make a client stub
As the second parameter from the client, we’ll call the getAll method specified in Server’s addService method, as seen below.
const PROTO_PATH = “./students.proto”;
const grpc = require(“@grpc/grpc-js”);
var protoLoader = require(“@grpc/proto-loader”);
var packageDefinition=protoLoader.loadSync(PROTO_PATH, {
longs: String,
oneofs: true,
keepCase: true,
enums: String,
defaults: true,
});
const StudentService = grpc.loadPackageDefinition(packageDefinition).StudentService;
const client = new StudentService(
“localhost:30043”,
grpc.credentials.createInsecure()
);
getAll() returns a list of all students.
From the client variable, call the getAll method on the server.
…
const client = new Service(
“localhost:30043”,
grpc.credentials.createInsecure()
);
client.getAll(null, (err, data) => {
if (!err) throw err
console.log(data);
});
Now run the following client.js code:
// node client.js
{
Students: [
{
id: “a68b823c-7ca6-44bc-b721-fb4d5312cafc”,
name: “John Bolton”,
age: 22,
courseName: “Course 1”
},
{
id: “34415c7c-f82d-4e44-88ca-ae2a1aaa92b7”,
name: “John Bolton”,
age: 22,
courseName: “Course 2”
},
]
}
A gRPC service method has been successfully run from a gRPC client. After exporting the NewsService object, you can use it to call methods in another programme.
const PROTO_PATH = “./students.proto”;
const grpc = require(“@grpc/grpc-js”);
var protoLoader = require(“@grpc/proto-loader”);
var packageDefinition=protoLoader.loadSync(PROTO_PATH, {
longs: String,
oneofs: true,
keepCase: true,
enums: String,
defaults: true,
});
const StudentService = grpc.loadPackageDefinition(packageDefinition).StudentService;
const client = new StudentService(
“localhost:30043”,
grpc.credentials.createInsecure()
);
module.exports = client;
The client can now be imported into a different file. For each step we want to take, we’ll create a distinct file. We’ll create a test.js file that imports the client and calls the getAll method.
// test.js
const client = require(“./client”);
client.getAll(null, (err, data) => {
if (!err) throw err
console.log(data);
});
Add a Student record.
Create a new method for inputting data. Open the proto file and add an RPC with the name of the new method under services. Our method is called Insert in the StudentService service, as shown below.
…
service StudentService {
rpc GetAll (Empty) returns (StudentList) {}
rpc Insert (Student) returns (Student) {}
}
…
The service will accept the message from the Student and return the new Student’s object.
…
server.addService(StudentsProto.StudentService.service, {
getAll: (_, callback) => {
callback(null, {Students});
},
insert: (call, callback) => {
let Student = call.request;
Student.id = uuidv4();
Students.push(Student);
callback(null, news);
},
});
…
Remove a student
Now we’ll write the code to delete a Student. Here’s a bit of code for it.
…
service StudentService {
rpc GetAll (Empty) returns (StudentList) {}
rpc Insert (Student) returns (Student) {}
rpc Remove (Student) returns (Student) {}
}
message StudentRequestId {
string id = 1;
}
…
The request in this case is StudentRequestId, and the response will be an empty message.
Below is a piece of code from server.js.
…
remove: (call, callback) => {
let existingStudentIndex = Students.findnidex(
n =>n.id == call.request.id
);
If(existingStudentIndex != -1){
Students.splice(existingStudentIndex,1)
callback(null,{});
}
},
…
Make a change to an existing Student
We’ll add a method to the proto file to update the data.
…
service StudentService {
rpc GetAll (Empty) returns (StudentList) {}
rpc Insert (Student) returns (Student) {}
rpc Remove (Student) returns (Student) {}
rpc Update (Student) returns (Student) {}
}
…
The method takes a Student message and responds with a News object that has been changed. Below is the code for updating the student data.
…
update: (call, callback) => {
let existingStudent = Students.find(n=> n.id== call.request.id);
if(existingStudent){
existingStudent.name = call.request.name;
existingStudent.age = call.request.age;
existingStudent.CourseName =call.request.CourseName;
callback(null, existingStudent);
},
…
Obtain a Student
In the proto file, create a method:
…
service StudentService {
rpc GetAll (Empty) returns (StudentList) {}
rpc Get (Student) returns (Student) {}
rpc Insert (Student) returns (Student) {}
rpc Remove (Student) returns (Student) {}
rpc Update (Student) returns (Student) {}
}
…
The Get method returns a Student message and requires an ID as the request message. Here’s how it’s done in the server.js file:
…
get: (call, callback) => {
let Student = Students.find(n=>n.id == call.request.id)
if(Student) = {
callback(null, Student);
}
},
…
The call param object provides the id. The id is used to find the student item in the Students array that corresponds to the id. The callback function is invoked with the obtained student item as a parameter, resulting in the client receiving the student item.
// test.js
// get all news
const client = require(“./client”);
client.getAll({}, (error, students) => {
if (error) throw error;
console.log(students);
});
//add a students
client.insert(
{
name: “Title news 3”,
age: 11,
CourseName: “Image URL here”,
},
(err, students) => {
if (err) throw err;
console.log(“Successfully created a students.”);
}
);
// edit a student
client.update(
{
id: “a68b823c-7ca6-44bc-b721-fb4d5312cafc”,
name: “Title news 3”,
age: 11,
CourseName: “Image URL here”,
},
(err, students) => {
if (err) throw err;
console.log(“Successfully Updated a Students.”);
}
);
// delete a students
client.remove(
{
id: “34415c7c-f82d-4e44-88ca-ae2a1aaa92b7”,
},
(err, students) => {
if (err) throw err;
console.log(“Successfully deleted students record.”);
}
);
Now execute the following command:
node test
With Http server
We now have a working server, prototype, and client. Connect the client to a Node server. JavaScript, thus a method in the gRPC news service will be called from an endpoint on our server. The endpoints are listed below.
/GET endpoint will call the getAll sub-routine to get all the students in the database.
/save POST endpoint will call the insert sub-routine to create a new student item.
/update PUT will call the update sub-routine to edit/update a student item.
/remove DELETE will call the delete sub-routine to delete a student item.
Here’s the code in Nodejs:
const client = require(“./client”);
const express = require(“express”);
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) => {
if (!err) {
res.send(data.Students)
}
});
});
app.post(“/save”, (req, res) => {
console.log(req.body.CourseName)
let newStudent = {
name: req.body.name,
age: req.body.age,
CourseName: req.body.CourseName
};
client.insert(newStudent, (err, data) => {
if (err) throw err;
res.send({data:data, msg:”Student created successfully”})
});
});
app.post(“/update”, (req, res) => {
const updateStudent = {
id: req.body.id,
name: req.body.name,
age: req.body.age,
CourseName: req.body.CourseName
};
client.update(updateStudent, (err, data) => {
if (err) throw err;
res.send({msg:”Student updated successfully”})
});
});
app.post(“/remove”, (req, res) => {
client.remove({ id: req.body.Student_id }, (err, _) => {
if (err) throw err;
console.log(“Student removed successfully”);
//res.redirect(“/”);
res.send({msg:”Student removed successfully”})
});
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(“Server running at port %d”, PORT);
});
Conclude
So, this was about how to use NodeJS to construct gRPC services. I hope your goal for coming to this tutorial was accomplished. If you’re interested in learning more about NodeJS, head over to the NodeJS tutorials website. Suggestions and feedback are always welcome. If you have any questions, please contact us. Hire Node.JS Developer from IndyLogix with both basic and expert knowledge; contact us if you need to hire NodeJS developers for your app.