I would not emulate the benchmark code, except that it is async. The benchmark code is pretty heavily tuned to the usage pattern of benchmark work, which may not be ideal for your use.
From your work description, it sounds like to want to make the workers be servers, and the master be a client. A client can contact the workers with a work unit, and each worker will respond to it. That would be the Unary usage. If you want each worker to be working on at most n things as a time, you can make a map of gRPC stubs to work items. When a stub returns false for "CallStreamObserver.isReady()" you can register a callback (setOnReadyHandler() )on the observer to re add itself to the map of available workers. That way you limit workers to at most n work items, and only those which are not in flow control push back.
I am kind of guessing what you want from your description, and I don't know the specifics for your problem, but the async stub usage sounds right for you.