Почему я получаю Запрещенное сообщение от AWS API Gateway, даже если все работает внутренне? - PullRequest
14 голосов
/ 18 мая 2019

У меня есть настройка шлюза AWS API для публичной конечной точки без авторизации. Он подключается к веб-сокету, который запускает лямбду.

Я создавал соединения с websocket-client lib Python на https://pypi.org/project/websocket_client/.

Я заметил, что соединения будут выходить из строя ~ 10% времени и ухудшаться по мере увеличения нагрузки. Я не могу найти нигде, что могло бы задушить меня, поскольку мои общие настройки API Gateway говорят Your current account level throttling rate is 10000 requests per second with a burst of 5000 requests.. Дело в том, что всего 2-3 запроса в секунду будут вызывать проблемы довольно часто.

Между тем реакция на сбой будет выглядеть как {u'message': u'Forbidden', u'connectionId': u'Z2Jp-dR5vHcCJkg=', u'requestId': u'Z2JqAEJRvHcFzvg='}

Я вошел в свои данные журнала CloudWatch и искал идентификатор соединения и идентификатор запроса. Группа журналов для шлюза API не найдет результатов ни с одним идентификатором. Тем не менее поиск по моей лямбде, которая запускается при соединении через веб-сокет, будет иметь журнал с этим идентификатором соединения. Журнал показал, что все работает, как и ожидалось с нашей стороны. Лямбда просто запускает MySQL-запрос, который запускается.

Зачем мне получать ответ «Запрещено», несмотря на то, что лямбда работает так, как ожидалось?

Существующий вопрос на получении сообщения: запрещенный ответ от шлюза AWS API , кажется, решает вопрос, если он ВСЕГДА возвращает запрещенные для некоторых частных конечных точек. Ничто не выровнялось с моим случаем использования.

UPDATE

Я думаю, это может быть связано с locust.io или python, который я использую для подключения каждую секунду. Я установил https://www.npmjs.com/package/wscat на свою машину и подключаюсь и закрываюсь как можно быстрее. Я не получаю Forbidden сообщения. Это просто очень запутанно, так как я не уверен, как способ, которым я соединяюсь, будет случайным образом выплевывать обратно Forbidden сообщение иногда .

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')

enter image description here

Обновление 2

Я включил журналы доступа, один тип журнала, которого там не было раньше. Теперь я вижу, что мои лямбды всегда получают 200 без проблем. 403 прибывает из некоторого MESSAGE eventType, который не достигает фактического routeKey. Не знаю, откуда он, но вполне уверен, что ответ поможет.

Я также смог подтвердить, что нет никаких проблем с ENI.

enter image description here

Ответы [ 2 ]

4 голосов
/ 20 мая 2019

Возможно, вы столкнулись с некоторыми ограничениями, связанными с VPC.См. https://winterwindsoftware.com/scaling-lambdas-inside-vpc/. Звучит так, как будто у вас закончились ENI.Вы можете попробовать переместить функцию в другой VPC.Как долго работает каждый вызов лямбды?А на каком языке вы написали лямбду?

0 голосов
/ 28 мая 2019

Полезная нагрузка в моем примере пуста. API настроен на использование $request.body.action, чтобы знать routeKey. При подключении работает маршрут по умолчанию $connect.

Добавление правильного action в моё тело заставило 403 уйти. Это решение. По сути, я получал 200 ответов от акта подключения и отключения, но получал 403 всякий раз, когда мое сообщение без полезной нагрузки проходило.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...