Getting Throttling Exception on AWS CLI calls as ThrottlingException error
Asked Answered
B

1

5

I was trying to explore a new AWS service named Workspaces through AWS CLI and it seems to have the ability to cater 1 request/sec. When I try to hit multiple times simultaneously, it throws ThrottlingException error. Since workspaces is not in boto package as of yet so I am using CLI in python by subprocess calls.

    def describe_workspaces():
        process=subprocess.Popen(access_endpoint.split(), stdout=subprocess.PIPE)
        output=process.communicate()[0]

So, if I call this function >=1/sec, I will have ThrottlingException. How to handle that? And there will be multiple users calling this function simultaneously.

I was thinking of doing batching and async calls but how to fit in this architecture?

Biquadrate answered 7/5, 2015 at 14:38 Comment(6)
consider using boto: boto.readthedocs.org/en/latestProlong
but boto as of now doesn't have "workspaces" service thats why using subprocess to use aws cli.Biquadrate
How about using boto3? Sure, it's developer preview, but at least you can get a good idea of how it should be implemented. (boto3 is developed and maintained mainly by AWS staff) -- boto3.readthedocs.org/en/latest/reference/services/…Embryectomy
but it will be some time when boto3 will be released so I am left with using aws cli for now. Any way to get away with throttling exception? I am more interested in finding solution for this that fits this architecture. It would be a good learning for me because I cant think of any solution that fits in this.Biquadrate
I doubt the throttling is related to capability of the platform, but instead is likely a protective control targeted towards a different API action but overly broad in scope; still, I'm not sure I understand why you would need to call describe_workspaces more than once per second... or anything in the workspaces API, for that matter. Can you clarify?Anisette
actually, it will be for other people to access and see their workspaces..so it will be called "n" number of times and rate of function calling can be arbitrary. Does it clarify my intent?Biquadrate
B
10

New Solution:

You can resolve this using Config from botocore.config provided by Boto3, which is an AWS SDK in Python, by specifying retry configuration as shown below in the code snippet:

import boto3 
from botocore.config import Config

def describe_workspaces():
    workspaces_client = boto3.client('workspaces', config=Config(connect_timeout=5, read_timeout=60, retries={'max_attempts': 5}))
    return workspaces_client.describe_workspaces()

References:


Old Solution:

You can resolve this using Boto3, which is an AWS SDK in Python, by adding an exception handling for ThrottlingException and retrying as shown below in the code snippet:

import boto3
from botocore.exceptions import ClientError

def describe_workspaces(tries=1):
    try:
        return boto3.client('workspaces').describe_workspaces()
    except ClientError as exception_obj:
        if exception_obj.response['Error']['Code'] == 'ThrottlingException':
            if tries <= 3:
                print("Throttling Exception Occured.")
                print("Retrying.....")
                print("Attempt No.: " + str(tries))
                time.sleep(3*tries)
                return describe_workspaces(tries + 1)
            else:
                print("Attempted 3 Times But No Success.")
                print("Raising Exception.....")
                raise
        else:
            raise

You can create an AWS client outside the function and can modify the logic as required.

You can handle ThrottlingException via AWS CLI as well but it would make more sense if you write some Bash/Shell script instead of a Python script. For Python, Boto3 is recommended.

For more details, check out the following: AWS Workspaces APIs


Generic Old Solution:

If your code has multiple (more than one) AWS client calls and you don't want to add the same code for ThrottlingException handling and retrying again and again to each call in order to achieve reusability (DRY; Don't repeat yourself) and avoid unnecessary code repetition, you can use the following code snippet:

import time
import boto3
from botocore.exceptions import ClientError

def generic_aws_client_method(client, method_name, method_arguments, tries=1):
    """Generic AWS client method with throttling exception handling"""
    try:
        client_method = getattr(client, method_name)
        return client_method(**method_arguments)
    except ClientError as exception_obj:
        if exception_obj.response['Error']['Code'] == 'ThrottlingException':
            if tries <= 3:
                print("Throttling Exception Occured.")
                print("Retrying.....")
                print("Attempt No.: " + str(tries))
                time.sleep(3*tries)
                return generic_aws_client_method(
                    client,
                    method_name,
                    method_arguments,
                    tries + 1
                )
            else:
                print("Attempted 3 Times But No Success.")
                print("Raising Exception.....")
                raise
        else:
            raise

Below you can find some examples on how to use it:

# AWS clients for AWS S3 and AWS SSM respectively
s3_client = boto3.client('s3')
ssm_client = boto3.client('ssm')

# Example 1: With multiple method arguments
mapping = {'Name': '/prod/aws-eks-vpc-id', 'WithDecryption': True}
returned_object = generic_aws_client_method(ssm_client, "get_parameter", mapping)
print(returned_object)

# Example 2: With single method argument
mapping = {'operation_name': 'describe_parameters'}
returned_object = generic_aws_client_method(ssm_client, "get_paginator", mapping)
print(returned_object)

# Example 3: With no method argument
mapping = {}
returned_object = generic_aws_client_method(s3_client, "list_buckets", mapping)
print(returned_object)

Testing ThrottlingException Handling:

In order to test the ThrottlingException handling in the above code snippets, use the following code snippet to raise a custom ClientError by yourself:

raise ClientError(
    {'Error': {'Code': 'ThrottlingException', 'Message': 'Rate exceeded'}},
    'generic_aws_client_method'
)
Blastopore answered 30/7, 2019 at 6:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.