5
\$\begingroup\$

The .proto file is as below:

syntax = "proto3";

package bamboo;

// -----------------Cart service-----------------

service CartService {
    rpc AddItem(AddItemRequest) returns (Empty) {}
    rpc GetCart(GetCartRequest) returns (Cart) {}
    rpc EmptyCart(EmptyCartRequest) returns (Empty) {}
}

message CartItem {
    string product_id = 1;
    int32  quantity = 2;
}

message AddItemRequest {
    string user_id = 1;
    CartItem item = 2;
}

message EmptyCartRequest {
    string user_id = 1;
}

message GetCartRequest {
    string user_id = 1;
}

message Cart {
    string user_id = 1;
    repeated CartItem items = 2;
}

message Empty {}

And I have a Cart service on gRPC that is as simple as below:

from grpczoo import bamboo_pb2_grpc, bamboo_pb2
from concurrent import futures
import grpc
import time


class CartService(bamboo_pb2_grpc.CartServiceServicer):
    def AddItem(self, request, context):
        print(request.user_id, request.item)
        return bamboo_pb2.Empty()


if __name__ == "__main__":
    channel = grpc.insecure_channel('127.0.0.1')
    cart_stub = bamboo_pb2_grpc.CartServiceStub(channel)

    # create gRPC server
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))

    # add class to gRPC server
    service = CartService()
    bamboo_pb2_grpc.add_CartServiceServicer_to_server(service, server)

    # start server
    server.add_insecure_port('[::]:9000')
    server.start()

    # keep alive
    try:
        while True:
            time.sleep(10000)
    except KeyboardInterrupt:
            server.stop(0)

Let's assume that starting a service like above seems good when you have 40 services (We can create a base class for starting a service)

The most annoying part of the system is where I have to initiate a client when I need to send a RPC call to a service (here cart service):

import grpc

# set up server stub
from grpczoo import bamboo_pb2_grpc, bamboo_pb2

channel = grpc.insecure_channel('localhost:9000')
stub = bamboo_pb2_grpc.CartServiceStub(channel)
# form request
request = bamboo_pb2.AddItemRequest(user_id="123", item={'product_id': '21', 'quantity': 2})

# make call to server
response = stub.AddItem(request)
print(response)

As you can see for a simple RPC call like above I have to open channel to that service and form a request and then call the remote method AddItem. In a real world micro-service project I have to call at least 5 different methods and for each I have to create a channel and for the request and so on.

The question is how should I manage RPC calls to different methods when project gets bigger and I have 20 to 50 different services? The above code does not seems maintainable at all. How do you handle such cases?

\$\endgroup\$
  • \$\begingroup\$ You should change your title according to Titling your question to make it more descriptive. \$\endgroup\$ – AlexV May 8 at 18:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.