[zeromq-dev] [pyzmq]: Asynchronous client api design
Kenneth Adam Miller
kennethadammiller at gmail.com
Mon Mar 9 19:25:38 CET 2015
Inline.
On Mon, Mar 9, 2015 at 7:12 AM, Yassine Lamgarchal <bouceka78 at gmail.com>
wrote:
> Hi Kenneth,
>
> Thank you for your quick response !
>
> * I use a DEALER socket because the client must be able to send multiple
> commands without
> receiving the response:
>
> - async_result1 = client.command("data1")
> - async_result2 = client.command("data2")
> - .... do other stufs ....
> - result1 = async_result1.get()
> - result2 = async_result2.get()
>
> * Indeed, it looks like a future object :) !
>
> * Yea, in the schema it's a thread which run the event loop and listen for
> commands to send to the server, i
> think i can easily spawn a process instead of a thread. The consumer
> simply connect to the socket, on
> which the thread listen on, and send commands.
>
> * Thanks, i realize that a REQ socket is better in this case because a
> PAIR will restrict to only one client
> connected to the "framework thread".
>
> Q1. Well, for now there is a fixed number of servers known by each client.
> When the cluster start it elects a server as
> a leader, the command are only sent to that particular server. So for now,
> there is no need to load balance the requests.
>
So, if you wrapped the connection initialization portion along with the
service loop in an additional endpoint selection loop in the api, you could
easily abstract over the use of a broker. If you haven't seen the new
malamute broker that's being developed, if the test in the loop you did
actually return or set some kind of targeted server address then you could,
in the connect call to the server, pass a string that's set depending on
the model that you select.
>
> Q2. Yea, the thing is as a user i don't like when a library create threads
> in the background, this could lead to bugs hard
> to troubleshoot. But yea with message passing this could be acceptable.
>
Well, ideally libraries should not do this, but in fact even ZeroMQ does
this. If you didn't know it, when you create a context it is in fact a
runtime as well, creating threads in the background that do things such as
make sure that your data gets sent reliably and is received and placed into
the proper framing and some such. It's interesting because the only way
that it imposes any change on the user is it forces that, on shutdown the
user not have any remaining sockets that haven't been properly
deallocated/collected. But that's good practice anyway. So generally, if
you design your library so that it doesn't expose any dependency to
consumer code, then you should be in good shape.
>
> Actually, i thought if i can have the same behavior (then having a single
> threaded client application) and letting the user
> create the event loop. If i do so, the client application must be fully
> event driven (the client event loop receive events
> and send commands) but i don't want this. In my use case i think that
> "framework thread" is mandatory, does my reasoning
> make sense ? :)
>
No, I don't know exactly what you're referencing, because my questions
ended at your above response. This seems to be a newer, different topic.
Please explain what you mean more.
>
>
> --
> Yassine
>
>
> 2015-03-09 3:16 GMT+01:00 Kenneth Adam Miller <kennethadammiller at gmail.com
> >:
>
>> Replied inline
>>
>> On Sun, Mar 8, 2015 at 7:55 PM, Yassine Lamgarchal <bouceka78 at gmail.com>
>> wrote:
>>
>>> Hello all o/,
>>>
>>> I'm currently designing a distributed application which is composed of
>>> clients
>>> and a remote server.
>>>
>>> I struggle with the asynchronous client api... I want it to be the most
>>> simple
>>> to use and to implement.
>>>
>>> Here is some background: the clients can send commands, when the server
>>> receive the
>>> command it does some work and response back to the client. For that, i
>>> use a DEALER
>>> socket in the client side and a ROUTER socket in the server side because
>>> i want the
>>> client and the server to be asynchronous. In addition, the client can
>>> receive some
>>> unexpected event messages.
>>>
>>>
>> Why not a request socket in the client?
>>
>>
>>> An UUID is associated to each command.
>>>
>>>
>>> What i want to do, from a user point of view, is something like that:
>>>
>>> - async_result = client.command("some_data") # send the command to
>>> the server
>>> - ... do other stufs ...
>>> - result = async_result.get() # block until the response is available
>>>
>>>
>> Sounds a lot like a future/promise relationship.
>>
>>
>>> Here is a schema of what i imagined so far:
>>> http://postimg.org/image/qxyazo2st
>>>
>>
>> Nice schema. Have you thought about adding the possibility of this
>> asynchronous command being made into a library? Possibly even it's own
>> process and therefore daemon? Would be interesting to do so, with python's
>> first class modules, you could easily implement the same send and receive
>> API, so any consumer could just as easily take advantage of the library
>> features by simply importing a different module.-
>>
>>>
>>>
>>> In this design, there is a thread which run an event loop, this event
>>> loop will listen
>>> to a PAIR socket which make the client able to interact with it
>>> and tells it to send commands.
>>>
>>
>> Req socket would do this, but ok.
>>
>>
>>>
>>> When the server send the response, the event loop handler will put the
>>> response on
>>> a data structure with the command UUID. The client can retrieve the
>>> response thanks
>>> to the command UUID.
>>>
>>> So there is a synchronization to do between the main application thread
>>> and the
>>> "framework thread".
>>>
>>> My questions are the following:
>>>
>>> 1. Do you think its a simple design for this purpose ?
>>>
>>
>> Well, have you thought about the possibility of adding additional
>> servers? This would easily get hard in that each client would never every
>> server's address/config info... you could easily put a load balancing
>> broker in here for easy scalability. It could do nothing but facilitate
>> connection information exchange for direct direct communication. In this
>> way, you preserve the entire communication model you've already designed,
>> but also get more scalability.
>>
>>
>>> 2. Is it possible to avoid the use of a "framework thread"(and then
>>> avoid threads synchronization) ?
>>>
>>>
>> Thread synchronization shouldn't be so hard with message passing
>> semantics under the hood, if you just have the API hide this complexity.
>>
>> By the way, while I'm writing everything, I'm wondering if it's actually
>> already been done... *hint :)
>>
>>
>>>
>>> Thank you for your help in advance :) !
>>>
>>> --
>>> Yassine
>>>
>>>
>>> _______________________________________________
>>> zeromq-dev mailing list
>>> zeromq-dev at lists.zeromq.org
>>> http://lists.zeromq.org/mailman/listinfo/zeromq-dev
>>>
>>>
>>
>> _______________________________________________
>> zeromq-dev mailing list
>> zeromq-dev at lists.zeromq.org
>> http://lists.zeromq.org/mailman/listinfo/zeromq-dev
>>
>>
>
> _______________________________________________
> zeromq-dev mailing list
> zeromq-dev at lists.zeromq.org
> http://lists.zeromq.org/mailman/listinfo/zeromq-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.zeromq.org/pipermail/zeromq-dev/attachments/20150309/bc200cf0/attachment.htm>
More information about the zeromq-dev
mailing list