[python-ldap] ldap.OPT_DESC, async ops and paged search controls

Mark R Bannister mark at proseconsulting.co.uk
Tue Jan 27 22:13:24 CET 2015


On 27/01/2015 20:52, Michael Ströder wrote:
> Mark R Bannister wrote:
>> The original design limits the number of threads in an attempt to be more
>> scalable.  There is a fixed number of workers that can each be responsible for
>> a larger number of LDAP connections.  This is by design.  If I launched a new
>> blocking thread for each LDAP connection, it would be easy to overload the
>> system with too many threads by sending in many different requests
>> simultaneously.
> I don't know what you're after.
>
> I thought you have many incoming requests and you want to handle them
> completely asynchronously placing incoming requests into a queue. You could
> send many LDAP requests to the server without blocking and dispatch the
> incoming responses to the original requests in the queue.
>
> Ciao, Michael.
>
Indeed, which is more-or-less how's it's done.  But you spoke of having 
a blocking thread reading results back from the directory server, and I 
don't see how that could be an improvement.

Here is a rough diagram of how it currently works.One half of the jigsaw 
puzzle is implemented by my Pyloom library 
(https://sourceforge.net/p/dbis/code/ci/default/tree/src/pyloom/__init__.py.in). 
One listen socket, some marshal threads that pick up incoming requests 
and dispatch to a separate group of worker threads:

             [listen socket]
        ____________|____________
        |           |           |
    [marshal]   [marshal]   [marshal]
    ____|____   ____|____   ____|____
    |   |   |   |   |   |   |   |   |
   [w] [w] [w] [w] [w] [w] [w] [w] [w]

The worker thread itself is implemented in the DBIS Server class 
(https://sourceforge.net/p/dbis/code/ci/default/tree/src/dbis/server.py) 
and has a queue of work, each which may have its own LDAP object (or a 
reference to another session that is currently looking up the 
information it needs):

   [w] +--> [session 1] ---> [LDAP object]
       |
       +--> [session 2] ---> [LDAP object]
       |
       +--> [session 3] ---> [waiting on another session]
       |
       ... etc.

As you can see, I may have many LDAP objects in different states, and 
it's all asynchronous, but importantly I have a fixed number of 
threads.  The only thing that is dynamic is the size of a worker's 
queue, i.e. the number of sessions a worker thread is actively managing 
may go up or down, to an uppper limit, but the total number of running 
threads stays the same.  Each worker relies on a select() call to wake 
it up, and there may be a number of things that wakes a worker up (new 
incoming request from marshal thread, new incoming data from running 
LDAP search operation, data now available in watched session, server 
shutdown message).

Now what I don't follow is your suggestion of using a blocking thread to 
read results back from an LDAP search operation.  For that to work, I 
would need a much greater number of threads running, one per LDAP 
object.  I don't see how that would improve anything, I can only see it 
making the server perform more poorly when under heavy load.  But maybe 
I'm missing something here ...

Best regards,
Mark.



More information about the python-ldap mailing list