Too many open files (CLOSE_WAIT connections)

I'm importing data from a remote API. It's not the best API, so it requires me to do a lot of requests for any given data point. Since the data isn't time invariant, I need to first get a full set and then import it. Both sides use requests to talk to REST endpoints. The problem is that because I need to import one whole dataset all at once, I have a pretty long running celery task. In our test environment, everything worked great, so I'm ruling out business logic errors, but maybe I or a library provider is using requests wrong -- or this is a bug. 

## Problem

In my production environment, I get 

`
HTTPSConnectionPool(host='<redacted>', port=443): Max retries exceeded with url: /rest/api/2/<redacted> (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x7f05734547b8>: Failed to establish a new connection: [Errno 24] Too many open files',))
`
## Expected Result

New connections can be made while respecting `/etc/security/limits.conf` (which in my case sets nofile to 10240). Requests manages open file descriptors for `CLOSE_WAIT` sockets and recycles them as appropriate. 

## Actual Result

New connections cannot be made after a certain point. I suspect this might be 1024, because when monitoring `lsof -i | grep CLOSE_WAIT | wc -l`, it never exceeds this number. 
Calling `gc.collect()` after importing parts of the data does not help. `CLOSE_WAIT` socket file descriptors are only released once the celery task completes and the whole process ends. The next run looks similar, so it seems at least when the process ends, everything is cleaned up properly. 

## Reproduction Steps

Honestly I don't know what to put here, because I'm just using API wrappers. Please tell me what you need to know. I can tell you this happens independently with both ingress and egress wrappers (which talk to entirely different systems and APIs), and a colleague and I have tried to find any held references and have found none.  

## System Information

    $ python -m requests.help

```
{
  "chardet": {
    "version": "3.0.4"
  },
  "cryptography": {
    "version": "2.0.3"
  },
  "idna": {
    "version": "2.6"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.6.4"
  },
  "platform": {
    "release": "4.4.0-109-generic",
    "system": "Linux"
  },
  "pyOpenSSL": {
    "openssl_version": "1010006f",
    "version": "17.2.0"
  },
  "requests": {
    "version": "2.18.4"
  },
  "system_ssl": {
    "version": "1000207f"
  },
  "urllib3": {
    "version": "1.22"
  },
  "using_pyopenssl": true
}
```


Maybe help for you:
 " a lot of close/wait usually means that there are a lot of connections being opened and closed rapidly. It takes time for those connections to be cleared on the server even with a proper request to close which is normal TCP operation. I'd suggest you review your code to see if something is potentially leaking connecting or closing them too soon before they have a chance to be re-used. That could be the root of the problem."

Come from here: https://groups.google.com/forum/#!msg/gremlin-users/Psh0N9RpGuM/95yLrdNrEQAJ

I also have the same problem. After debugging, I found its the bug of code.
Here is a simple bug code example:
```
import requests
from proj.celery import app

SESSION = requests.session()

class Client:
    def __init__(self):
        self.proxies = get_proxies()
    def get(self, params=None, url=None, path=None, headers=None, timeout=10):
        resp = SESSION.get(url, params=params, headers=headers, timeout=timeout, proxies=self.proxies)
        return resp

@app.task
def test_task():
    c = Client()
    c.get('https://google.com')
```
When we run test_task on celery-daemon many times, it will remain many 'close_wait' state connection to celery. 
You can use `netstat -anutp |grep 'CLOSE_STAT'` to see the useless connection fd for celery process.

So I move the session into Client as a attr to solve my problem. 
```
class Client:
    def __init__(self):
        self.proxies = get_proxies()
        self.session = requests.SESSION()
    def get(self, params=None, url=None, path=None, headers=None, timeout=10):
        resp = self.session.get(url, params=params, headers=headers, timeout=timeout, proxies=self.proxies)
        return resp
```
This is my experience, I hope it can help others.

In an effort to clean up the issue tracker to only have issues that are still relevant to the project we've done a quick pass and decided this issue may no longer be relevant for a variety of potential reasons, including:

* Applies to a much older version, unclear whether the issue still applies.
* Change requires a backwards incompatible release and it's unclear if the benefits are worth the migration effort from the community.
* There isn't a clear demand from the community on the change landing in Requests.

If you think the issue should remain open, please comment so below or open a new issue and link back to the original issue. Again, thank you for opening the issue and for the discussion, it's much appreciated.