boto3: Exceptions coming from boto3/botocore when running boto3.client('sts') too many times simultaneously
import boto3, threading
for i in range(50):
threading.Thread(target=lambda: boto3.client('sts')).start()
And you get, tested on my Windows 10 machine (boto3 version 1.5.31, botocore version 1.8.45) and also on an Amazon Linux EC2, a bunch of exceptions like this:
Exception in thread Thread-20:
Traceback (most recent call last):
File "C:\Program Files (x86)\Python35-32\lib\threading.py", line 914, in _bootstrap_inner
self.run()
File "C:\Program Files (x86)\Python35-32\lib\threading.py", line 862, in run
self._target(*self._args, **self._kwargs)
File "<stdin>", line 2, in <lambda>
File "C:\Users\alexander.monk\AppData\Roaming\Python\Python35\site-packages\boto3\__init__.py", line 83, in client
return _get_default_session().client(*args, **kwargs)
File "C:\Users\alexander.monk\AppData\Roaming\Python\Python35\site-packages\boto3\session.py", line 263, in client
aws_session_token=aws_session_token, config=config)
File "C:\Users\alexander.monk\AppData\Roaming\Python\Python35\site-packages\botocore\session.py", line 850, in create_client
credentials = self.get_credentials()
File "C:\Users\alexander.monk\AppData\Roaming\Python\Python35\site-packages\botocore\session.py", line 474, in get_credentials
'credential_provider').load_credentials()
File "C:\Users\alexander.monk\AppData\Roaming\Python\Python35\site-packages\botocore\session.py", line 926, in get_component
del self._deferred[name]
KeyError: 'credential_provider'
or:
Exception in thread Thread-24:
Traceback (most recent call last):
File "C:\Program Files (x86)\Python35-32\lib\threading.py", line 914, in _bootstrap_inner
self.run()
File "C:\Program Files (x86)\Python35-32\lib\threading.py", line 862, in run
self._target(*self._args, **self._kwargs)
File "<stdin>", line 2, in <lambda>
File "C:\Users\alexander.monk\AppData\Roaming\Python\Python35\site-packages\boto3\__init__.py", line 83, in client
return _get_default_session().client(*args, **kwargs)
File "C:\Users\alexander.monk\AppData\Roaming\Python\Python35\site-packages\boto3\session.py", line 263, in client
aws_session_token=aws_session_token, config=config)
File "C:\Users\alexander.monk\AppData\Roaming\Python\Python35\site-packages\botocore\session.py", line 851, in create_client
endpoint_resolver = self.get_component('endpoint_resolver')
File "C:\Users\alexander.monk\AppData\Roaming\Python\Python35\site-packages\botocore\session.py", line 726, in get_component
return self._components.get_component(name)
File "C:\Users\alexander.monk\AppData\Roaming\Python\Python35\site-packages\botocore\session.py", line 926, in get_component
del self._deferred[name]
KeyError: 'endpoint_resolver'
Normally seems to be several credential_provider ones followed by several endpoint_resolver ones. The chance of getting these exceptions seems to increase with the number of threads.
About this issue
- Original URL
- State: open
- Created 6 years ago
- Reactions: 16
- Comments: 18 (6 by maintainers)
Commits related to this issue
- ComponentLocator.get_component: Fix thread safety By locking around multiple operations on self._deferred Fixes https://github.com/boto/boto3/issues/1592 — committed to moalexmonk/botocore by moalexmonk 6 years ago
- Fix occasional "endpoint_resolver" failures It seems that the boto3 library is not threadsafe. The solution discussed in GitHub issues such as https://github.com/boto/botocore/issues/1246 https... — committed to caltechlibrary/handprint by mhucka 4 years ago
- fix(utils): enforce thread safety for boto3 clients ref: https://github.com/boto/boto3/issues/1592 — committed to shaftoe/api-l3x-in by shaftoe 4 years ago
- fix(logging): race condition in S3 logging The 'boto3.client' method is not thread safe: https://github.com/boto/boto3/issues/1592 Put a lock around initializing an S3 client, so the two threads tha... — committed to hedyorg/hedy by rix0rrr 3 years ago
- fix(logging): race condition in S3 logging (#540) The 'boto3.client' method is not thread safe: https://github.com/boto/boto3/issues/1592 Put a lock around initializing an S3 client, so the two th... — committed to hedyorg/hedy by rix0rrr 3 years ago
- Create a new `boto3.Session()` per `S3ObjectStore` instance (#1260) `boto3` sessions are not thread safe. When used in the object store logger with `use_procs: False`, the default session was shared... — committed to mosaicml/composer by ravi-mosaicml 2 years ago
- Create a new `boto3.Session()` per `S3ObjectStore` instance (#1260) `boto3` sessions are not thread safe. When used in the object store logger with `use_procs: False`, the default session was shared... — committed to mosaicml/composer by ravi-mosaicml 2 years ago
- (BSR)[API] fix: Fix non-thread safe usage of boto3 client in outscale connector `boto3.client()` is not thread-safe. We sometimes get the following error: KeyError: 'default_config_resolver' ... — committed to pass-culture/pass-culture-main by dbaty a year ago
- (BSR)[API] fix: Fix non-thread safe usage of boto3 client in outscale connector `boto3.client()` is not thread-safe. We sometimes get the following error: KeyError: 'default_config_resolver' ... — committed to pass-culture/pass-culture-main by dbaty a year ago
- (BSR)[API] fix: Fix non-thread safe usage of boto3 client in outscale connector `boto3.client()` is not thread-safe. We sometimes get the following error: KeyError: 'default_config_resolver' ... — committed to pass-culture/pass-culture-main by dbaty a year ago
- fix: Create boto2 session instance of ArtifactStorage. This should fix errors with client auth. See https://github.com/boto/boto3/issues/1592 and https://boto3.amazonaws.com/v1/documentation/api/late... — committed to DockStudios/jmon by MatthewJohn 10 months ago
So finally sessions and resources can be shared across threads or not? Immediately after I start using them as described in the docs I hit
KeyError: 'credential_provider'or similar. My threads do upload only so I guess I’m on safe side but I keep finding statements contradicting the docs.@zgoda-mobica , Same issue here. I had
ThreadPoolExecutorand each thread was invokingboto3.client('lambda').invoke()without usingSession()which throwsKeyError: 'credential_provider'error.So now using following in thread invoked method…
and it seems to be ok.
Workaround for this in the mean time: Put a
boto3.client('sts')call immediately before the for loop.Creating a Session is a very resource intensive process as it has to load and deserialize several models before it can create clients. If this was required every time a client was created we’d see unacceptable performance impact. It’s a rare use-case customers actually need individual sessions, so we avoid this by creating a single instance by default for reuse. If this is undesired behavior customers are free to instantiate their own Session as you’re showing.
With the code you’ve proposed above, it will have the same performance as creating one client currently. However, we see creating a client take ~15x longer once we start creating many clients. This is because we are currently amortizing that Session cost over each client creation by reusing a single DEFAULT_SESSION instance.
Performance Impact Example
We’ll see results over 1000 runs come out as seen below:
As you can see this quickly becomes cost prohibitive for time sensitive applications. This is why the current documentation instructs users to pass clients to threads rather than create them in the thread.
There is also an outstanding unanswered question in botocore about thread safety. Would be great to know what’s the actual correct approach should be.
You’re correct about this behavior. Historically we’ve said that session methods aren’t thread safe, but once you’ve created a client or resource, we guarantee that those calls are thread safe (http://boto3.readthedocs.io/en/latest/guide/resources.html#multithreading-multiprocessing).
While we can investigate changing that stance, I suspect there will be more work than just the component logic, though that’s a good start and one of the most common content points in sessions.
I documented the issue based on my own understanding. https://medium.com/@life-is-short-so-enjoy-it/aws-boto3-misunderstanding-about-thread-safe-a7261d7391fd
The documentation on multithreading was updated in this PR: https://github.com/boto/boto3/pull/2848.
Here are links to the multithreading documentation for Clients, Resources, and Sessions. Does that help clarify things?
The documentation says that it is “recommended” to create a resource per thread but the example code below that recommendation creates a resource AND a session per thread. IOW, it is ambiguous if sessions can be shared between threads or not. Further down, the documentation states that resources are NOT thread-safe. That would imply that it’s not merely “recommended” to create a resource per thread, but rather that it’s a requirement to do so.
I’m confused.