J'ai configuré la passerelle AWS API pour un point de terminaison public sans authentification. Il se connecte à une websocket qui déclenche une Lambda.
Je créais des connexions avec Python websocket-client
lib at https://pypi.org/project/websocket_client/ .
J'ai remarqué que les connexions échouaient ~ 10% du temps et s'aggravaient à mesure que j'augmentais la charge. Je ne trouve aucun endroit qui pourrait m'étouffer, car mes paramètres généraux de la passerelle API disent Your current account level throttling rate is 10000 requests per second with a burst of 5000 requests.
. C'est à côté du point que seulement 2-3 demandes par seconde déclencheraient un problème assez souvent.
Pendant ce temps, la réponse d'échec serait comme {u'message': u'Forbidden', u'connectionId': u'Z2Jp-dR5vHcCJkg=', u'requestId': u'Z2JqAEJRvHcFzvg='}
Je suis allé dans mes informations de journal CloudWatch et j'ai recherché l'ID de connexion et l'ID de demande. Le groupe de journaux de la passerelle API ne trouverait aucun résultat avec l'un ou l'autre ID. Pourtant, une recherche sur ma Lambda qui se déclenche sur la connexion Websocket, aurait un journal avec cet ID de connexion. Le journal montrait que tout fonctionnait comme prévu de notre côté. Le lambda exécute simplement une requête MySQL qui se déclenche.
Pourquoi devrais-je obtenir une réponse d'interdit, malgré le fonctionnement lambda comme prévu?
La question existante sur obtenir un message: réponse interdite de la passerelle AWS API , semble répondre si elle retourne TOUJOURS interdite pour certains points de terminaison privés. Rien ne correspondait à mon cas d'utilisation.
[~ # ~] mise à jour [~ # ~]
Je pense que cela peut être lié à locust.io
, ou python, que j'utilise pour me connecter à chaque seconde. J'ai installé https://www.npmjs.com/package/wscat sur ma machine et je me connecte et ferme le plus rapidement possible à plusieurs reprises. Je ne reçois pas de message Forbidden
. C'est juste déroutant car je ne sais pas comment la façon dont je me connecte cracherait au hasard un Forbidden
message parfois.
class SocketClient(object):
def __init__(self, Host):
self.Host = Host
self.session_id = uuid4().hex
def connect(self):
self.ws = websocket.WebSocket()
self.ws.settimeout(10)
self.ws.connect(self.Host)
events.quitting += self.on_close
data = self.attach_session({})
return data
def attach_session(self, payload):
message_id = uuid4().hex
start_time = time.time()
e = None
try:
print("Sending payload {}".format(payload))
data = self.send_with_response(payload)
assert data['mykey']
except AssertionError as exp:
e = exp
except Exception as exp:
e = exp
self.ws.close()
self.connect()
elapsed = int((time.time() - start_time) * 1000)
if e:
events.request_failure.fire(request_type='sockjs', name='send',
response_time=elapsed, exception=e)
else:
events.request_success.fire(request_type='sockjs', name='send',
response_time=elapsed,
response_length=0)
return data
def send_with_response(self, payload):
json_data = json.dumps(payload)
g = gevent.spawn(self.ws.send, json_data)
g.get(block=True, timeout=2)
g = gevent.spawn(self.ws.recv)
result = g.get(block=True, timeout=10)
json_data = json.loads(result)
return json_data
def on_close(self):
self.ws.close()
class ActionsTaskSet(TaskSet):
@task
def streams(self):
response = self.client.connect()
logger.info("Connect Response: {}".format(response))
class WSUser(Locust):
task_set = ActionsTaskSet
min_wait = 1000
max_wait = 3000
def __init__(self, *args, **kwargs):
super(WSUser, self).__init__(*args, **kwargs)
self.client = SocketClient('wss://mydomain.amazonaws.com/endpoint')
Mise à jour 2
J'ai activé les journaux d'accès, le seul type de journal qui n'existait pas auparavant. Je peux maintenant voir que mes lambdas obtiennent toujours un 200 sans problème. Le 403 provient d'un MESSAGE
eventType
qui n'atteint pas un routeKey
réel. Je ne sais pas d'où cela vient, mais je suis sûr que trouver cette réponse résoudra le problème.
J'ai également pu confirmer qu'il n'y avait pas de problème ENI.
La charge utile dans mon exemple est vide. L'API est configurée pour utiliser $request.body.action
pour connaître la routeKey. La connexion définit la valeur par défaut $connect
travaux routiers.
L'ajout d'un action
approprié dans mon corps a fait disparaître les 403. Voilà la solution. J'obtenais essentiellement 200 réponses de l'acte de connexion et de déconnexion, mais j'obtenais le 403 chaque fois que mon message sans charge utile passait.
Vous pourriez rencontrer certaines limites liées au VPC. Voir https://winterwindsoftware.com/scaling-lambdas-inside-vpc/ . On dirait que vous pourriez manquer d'ENI. Vous pouvez essayer de déplacer la fonction vers un autre VPC. Combien de temps dure chaque invocation du lambda? Et dans quelle langue êtes-vous lambda écrit?