Comment 9 for bug 1282089

Revision history for this message
Florent Flament (florentflament) wrote :

I agree, the bug seems to be related to connection pooling ... When using raw requests, the connections are released as soon as the response object is deleted. With connection pools, even though the responses are deleted, the connections are kept open (for reuse) until the connection pool is deleted.

Example:
>>> import requests
>>> r = requests.get("http://www.yahoo.fr")
>>> # $ lsof -p 5847 | grep TCP | wc -l --> 2
...
>>> del r
>>> # $ lsof -p 5847 | grep TCP | wc -l --> 0
...
>>> s = requests.Session()
>>> r = s.get("http://www.yahoo.fr")
>>> # $ lsof -p 5847 | grep TCP | wc -l --> 2
...
>>> del r
>>> # $ lsof -p 5847 | grep TCP | wc -l --> 2

What I think should be the good fix:

* Ideally, a unique Session object should be instanciated by each Opensack Dashboard worker (for instance as a class attribute) and shared accross all clients (keystoneclient, novaclient, ...). Horizon needs such 'global' attributes to be able to share objects accross requests. Moreover, Response objects should be closed (with close() method) or used inside "with" blocks, to avoid relying on GC.

* A reasonable fallback in keystoneclient would be to have a the requests.Session instance stored as an attribute of class keystoneclient.session.Session if not provided to constructor. Something like this:

class Session(object):
    ...
    session = requests.Session()

    def __init__( ..., session=None, ...)
        ...
        if session:
            self.session = session

@mouadino I think this solution is quite close to your proposal, although doesn't used a global variable (it uses a class attribute instead, which is almost the same). It also allows sharing a unique connection pool accross instances of keystoneclient and Horizon's requests. Now I understand the rationale of your proposal.