I must be doing something wrong... my gRPC server is implemented in node.js:
function handler(call, callback) {
console.log('Received request at ' + Date.now());
setTimeout(() => {
callback({ message: 'Done and done' });
}, 100);
}
If I call it 1,000 in Node, I get 1,000 responses in about 100ms:
const resps = [];
for (let i = 0; i < 1000; i += 1) {
client.doit({ data }, (err, resp) => {
resps.push(resp);
if (resps.length === 1000) {
onDone();
}
});
}
However, calling the server from Python using the service.future I can see the server only receiving a request after the previous one has returned:
for _ in range(1000):
message = Message(data=data)
resp = client.doit.future(message)
resp = resp.result()
resps.append(resp)
I get that Node's IO paradigm is different (everything is async; event loop; etc.), and the Python example above blocks on out.result()
, but my question is: can could I change/optimize the Python client so it can make multiple calls to my server without waiting for the first one to return?
You can make asynchronous unary calls in python like so:
class RpcHandler:
def rpc_async_req(self, stub):
def process_response(future):
duck.quack(future.result().quackMsg)
duck = Duck()
call_future = stub.Quack.future(pb2.QuackRequest(quackTimes=5)) #non-blocking call
call_future.add_done_callback(process_response) #non-blocking call
print('sent request, we could do other stuff or wait, lets wait this time. . .')
time.sleep(12) #the main thread would drop out here with no results if I don't sleep
print('exiting')
class Duck:
def quack(self, msg):
print(msg)
def main():
channel = grpc.insecure_channel('localhost:12345')
stub = pb2_grpc.DuckServiceStub(channel)
rpc_handler = RpcHandler()
rpc_handler.rpc_async_req(stub=stub)
if __name__ == '__main__':
main()
proto
syntax = "proto3";
package asynch;
service DuckService {
rpc Quack (QuackRequest) returns (QuackResponse);
}
message QuackRequest {
int32 quackTimes = 1;
}
message QuackResponse {
string quackMsg = 1;
}