Thank you for the detailed answer.
I have a mixture of trivial and time-consuming RPC calls, and the trivial ones
must execute quickly while a slow one is running.
I understand your remarks about threads, but the applications here are heavily
Windows-flavored, meaning there are no dedicated threads but completion ports,
tasks in the thread pool etc. I’d need to create a cache of sockets and that
seems to be more work than raw sockets. So, raw sockets it is.
I have browsed through rep.c (nng) and from what I can see the “cooked” mode
removes the header for incoming data, stores it in the member “btrace” and puts
it back into the reply. It also implements the lock that serializes the server
side. I assume here that rep0_sock_send and rep0_sock_recv are the highest
layer.
Can I make assumptions about the header content at the REP side? Is it always
just 4 bytes of pipe id? Or are the last 4 bytes the pipe id? I’d expect the
request ID from the client somewhere (see below).
Then I had a look at req.c. You use a request ID and I’ll need one too. You
append it to the header when sending and expect it the start of the header when
receiving. I’ll try that as well.
Jörn
Von: nanomsg-bounce@xxxxxxxxxxxxx [mailto:nanomsg-bounce@xxxxxxxxxxxxx] Im ;
Auftrag von Garrett D'Amore
Gesendet: Freitag, 16. Februar 2018 20:43
An: nanomsg@xxxxxxxxxxxxx
Betreff: [nanomsg] Re: RPC using nng, difficulties
Actually, REQ/REP is the right pattern, but because you need to handle multiple
outstanding requests at a time, you’ll have to do some more work in your
application code.
The easiest thing for your REQ application would be to open dedicated sockets
for each request (or concurrent request). You can reuse those sockets as you
like, but only one request can be outstanding on a time if you’re using the
default cooked mode. (If you’re using synchronous behavior, but using multiple
threads, then a socket per thread would do the trick.)
Somewhat more challenging would be to use raw mode (see the NNG_OPT_RAW socket
option for nng, or the AF_SP_RAW if you’re using legacy nanomsg). In this case
you have to examine headers, and match requests to responses. In order to get
the synchronous behavior you’ll have to add some kind of controls in your own
code — probably a condition variable, with suitable timeouts, etc. This can be
a fair bit of work, which is why if you can get by with multiple threads and
dedicated sockets I’d recommend doing so.
On the server side, you need to understand whether your request processing
truly needs to be asynchronous or not. Unfortunately I’ve not yet supplied a
demo for doing this with nng (I will do so soon), but there are demos for
threaded and asynchronous handling on the server side for libnanomsg. Again
this requires raw mode; I’d recommend the threaded model if you can use it —
this will automatically “limit” the amount of concurrent processing by the
number of active threads. Of course, if your requests are light weight (e.g.
returning a constant value, doing some cheap math, or something that doesn’t
require long running code) then you can just run a single threaded “recv/send”
loop on the server. This is the default, and by far the simplest.
Don’t mess with polyamorous mode — that’s not the behavior you want.
On Fri, Feb 16, 2018 at 2:57 AM Sierwald, Jörn
<Joern.Sierwald@xxxxxxxxxxxxx<mailto:Joern.Sierwald@xxxxxxxxxxxxx>> wrote:
G’day,
I’m trying to use nanomsg to do some remote procedure calls (replacing CORBA)
and I found that this is more painful than I expected.
The rep/req protocol cannot be used, as it serializes the calls at the server
and overwrites outstanding calls at the client end.
A client process must be able to call a remote function several times,
concurrently. Also, there will be several clients.
At the client the call should look synchronous.
I suspect the pair1 with “Polyamorous Mode” would be the correct basis. But
then I’d need to add wrappers at both end with some message counters, I guess.
Is this assumption correct?
Has it been done?
Is this even included in the distribution?
Would nng_device help in some way that I do not understand?
Would I have to write an entire protocol?
Should I abandon this and use a library that actually does RPC? (I am familiar
with native Microsoft-RPC)
BTW, I need other messaging than RPC, too, therefore the attempt to use a
generic messaging library.
Jörn