In this blog post, we will set up a basic gRPC communication system between a Node.js server and a Python client using Protocol Buffers (protobuf). We'll walk through the process step by step, including how to create and generate the necessary files, implement the server in Node.js, and the client in Python.
Prerequisites
- Node.js v22.11.0 or later
- Python 3.12.6 or later
- Familiarity with basic concepts of gRPC and Protocol Buffers
Step 1: Define the gRPC Service
We'll start by defining the gRPC service using Protocol Buffers (protobuf). Create a service.proto file in the root of your project directory. This will contain the structure of our messages and the service definition.
Here’s how the service.proto file will look:
syntax = "proto3";
package myservice;
service MyService {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
In this file:
- We define a service named
MyServicewith a methodSayHellothat takes aHelloRequestand returns aHelloReply. -
HelloRequestcontains anamefield for the name of the person to greet. -
HelloReplycontains amessagefield that will hold the greeting message.
Step 2: Install the necessary Node.js packages
npm init -y
npm install @grpc/grpc-js @grpc/proto-loader
Step 3: Implement the gRPC Server in Node.js
Once we have the generated files, we can now implement the gRPC server in Node.js.
- Create a
server.jsfile inside the Node.js backend folder. - Add the following code to implement the server:
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
// Load the service.proto file
const packageDefinition = protoLoader.loadSync('service.proto');
const myservice = grpc.loadPackageDefinition(packageDefinition).myservice;
// Implement the SayHello RPC method
function sayHello(call, callback) {
console.log("Received from Python:", call.request.name);
callback(null, { message: `Hello from Node.js, ${call.request.name}!` });
}
// Create the server and add the service
const server = new grpc.Server();
server.addService(myservice.MyService.service, { SayHello: sayHello });
// Start the server
server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => {
console.log('Node.js gRPC Server running on port 50051');
server.start();
});
In this code:
- We define the
SayHellomethod that logs the received name from the Python client and sends a greeting message. - The server listens on port
50051.
Step 4: Generate gRPC Code for Python
Next, we'll generate the Python code from the service.proto file to create a client that will communicate with the Node.js server.
Install the necessary Python packages:
pip install grpcio grpcio-tools
Generate the Python code:
Run the following command to generate the necessary Python files:
python -m grpc_tools.protoc -I. --python_out=./python-backend --grpc_python_out=./python-backend service.proto
This will generate two Python files:
service_pb2.pyservice_pb2_grpc.py
These files contain the generated classes for the HelloRequest and HelloReply messages, and the service stub to call the SayHello method.
Step 5: Implement the gRPC Client in Python
Now that we have the necessary Python files, we can create the Python client that will send a request to the Node.js server.
- Create a
client.pyfile inside the Python backend folder. - Add the following code:
import grpc
import service_pb2
import service_pb2_grpc
# Connect to the Node.js gRPC server
channel = grpc.insecure_channel('localhost:50051')
stub = service_pb2_grpc.MyServiceStub(channel)
# Send a request
response = stub.SayHello(service_pb2.HelloRequest(name="Muhammad"))
print("Response from Node.js:", response.message)
In this code:
- The client connects to the Node.js gRPC server running on
localhost:50051. - It sends a request with the name
"Muhammad"and receives the greeting message in return.
Step 6: Implement the Python Server
Now let's implement a Python server that will also be able to handle requests from the Node.js client.
- Create a
server.pyfile inside the Python backend folder. - Add the following code:
import grpc
from concurrent import futures
import time
import service_pb2
import service_pb2_grpc
# Define the server behavior
class MyServiceServicer(service_pb2_grpc.MyServiceServicer):
def SayHello(self, request, context):
print(f"Received from Node.js: {request.name}")
return service_pb2.HelloReply(message=f"Hello from Python, {request.name}!")
# Set up the server
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
service_pb2_grpc.add_MyServiceServicer_to_server(MyServiceServicer(), server)
server.add_insecure_port('[::]:50051')
print('Python gRPC Server running on port 50051')
server.start()
try:
while True:
time.sleep(86400)
except KeyboardInterrupt:
server.stop(0)
if __name__ == '__main__':
serve()
In this code:
- We define the
SayHellomethod in Python that sends back a message, acknowledging the request from Node.js. - The server listens on port
50051.
Step 7: Implement the Node.js Client
Lastly, we need to create a Node.js client that will communicate with the Python server.
- Create a
client.jsfile inside the Node.js client folder. - Add the following code:
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
// Load the service.proto file
const packageDefinition = protoLoader.loadSync('service.proto');
const myservice = grpc.loadPackageDefinition(packageDefinition).myservice;
// Create the client
const client = new myservice.MyService('localhost:50051', grpc.credentials.createInsecure());
// Call the SayHello method
client.SayHello({ name: 'Muhammad' }, (error, response) => {
if (!error) {
console.log('Response from Python:', response.message);
} else {
console.error(error);
}
});
In this code:
- The client connects to the Python gRPC server running on
localhost:50051. - It sends a request with the name
"Muhammad"and prints the response message.
Step 8: Run the Servers and Test the Communication
- Start the Python server by running the following command:
python server.py
- Start the Node.js server by running the following command:
node server.js
- Run the Python client:
python client.py
- Run the Node.js client:
node client.js
You should see the following output in both clients:
Response from Node.js: Hello from Node.js, Muhammad!
and
Response from Python: Hello from Python, Muhammad!
Conclusion
In this tutorial, we successfully set up a basic gRPC communication system between Node.js and Python. We learned how to:
- Define a gRPC service using Protocol Buffers.
- Generate the necessary code for both Node.js and Python.
- Implement the gRPC server in Node.js and Python.
- Implement the gRPC client in Node.js and Python.
- Test the communication between the two systems.
gRPC offers a robust, efficient, and language-agnostic framework for microservices, and it’s perfect for scenarios where performance and cross-platform communication are important.
Feel free to modify the code and experiment with more complex services. Happy coding!
Top comments (0)