DEV Community

Cover image for How to Set Up gRPC Communication Between Node.js and Python

How to Set Up gRPC Communication Between Node.js and Python

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;
}
Enter fullscreen mode Exit fullscreen mode

In this file:

  • We define a service named MyService with a method SayHello that takes a HelloRequest and returns a HelloReply.
  • HelloRequest contains a name field for the name of the person to greet.
  • HelloReply contains a message field 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
Enter fullscreen mode Exit fullscreen mode

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.

  1. Create a server.js file inside the Node.js backend folder.
  2. 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();
});
Enter fullscreen mode Exit fullscreen mode

In this code:

  • We define the SayHello method 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

This will generate two Python files:

  • service_pb2.py
  • service_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.

  1. Create a client.py file inside the Python backend folder.
  2. 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)
Enter fullscreen mode Exit fullscreen mode

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.

  1. Create a server.py file inside the Python backend folder.
  2. 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()
Enter fullscreen mode Exit fullscreen mode

In this code:

  • We define the SayHello method 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.

  1. Create a client.js file inside the Node.js client folder.
  2. 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);
  }
});
Enter fullscreen mode Exit fullscreen mode

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

  1. Start the Python server by running the following command:
   python server.py
Enter fullscreen mode Exit fullscreen mode
  1. Start the Node.js server by running the following command:
   node server.js
Enter fullscreen mode Exit fullscreen mode
  1. Run the Python client:
   python client.py
Enter fullscreen mode Exit fullscreen mode
  1. Run the Node.js client:
   node client.js
Enter fullscreen mode Exit fullscreen mode

You should see the following output in both clients:

Response from Node.js: Hello from Node.js, Muhammad!
Enter fullscreen mode Exit fullscreen mode

and

Response from Python: Hello from Python, Muhammad!
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this tutorial, we successfully set up a basic gRPC communication system between Node.js and Python. We learned how to:

  1. Define a gRPC service using Protocol Buffers.
  2. Generate the necessary code for both Node.js and Python.
  3. Implement the gRPC server in Node.js and Python.
  4. Implement the gRPC client in Node.js and Python.
  5. 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)