为什么我会收到来自 AWS API 网关的禁止消息,即使内部一切正常?
Why would I get a Forbidden message from AWS API Gateway, even though things are working internally?
我为 public 端点设置了 AWS API 网关,没有授权。它连接到触发 Lambda 的 websocket。
我正在与 Python 在 https://pypi.org/project/websocket_client/ 的 websocket-client
库建立连接。
我注意到大约 10% 的时间连接会失败,并且随着负载的增加而变得更糟。我找不到任何地方会限制我看到我的一般 API 网关设置说 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 日志洞察并搜索了连接 ID 和请求 ID。 API 网关的日志组找不到任何 ID 的结果。然而,在 websocket 连接上触发的对我的 Lambda 的搜索将有一个包含该连接 ID 的日志。日志显示了我们这边预期的一切 运行。 lambda 只是运行一个触发的 MySQL 查询。
为什么我会收到禁止响应,尽管 lambda 按预期工作?
getting message: forbidden reply from AWS API gateway 上的现有问题似乎解决了它是否总是返回禁止某些专用端点。没有符合我的用例的内容。
更新
我认为这可能与我每秒都在使用的 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')
更新 2
我启用了访问日志,这是一种以前没有的日志类型。我现在可以看到我的 lambda 总是毫无问题地得到 200。 403 来自一些 MESSAGE
eventType
并没有达到实际的 routeKey
。不确定它来自哪里,但很确定找到答案会解决这个问题。
我还能够确认没有 ENI 问题。
您可能 运行 遇到了一些 VPC-related 限制。参见 https://winterwindsoftware.com/scaling-lambdas-inside-vpc/。听起来您可能 运行 不再使用 ENI。您可以尝试将函数移动到不同的 VPC。 lambda 运行 的每次调用需要多长时间?你的 lambda 是用什么语言写的?
我的示例中的负载是空的。 API 被配置为使用 $request.body.action
来知道 routeKey。连接使默认 $connect
路由生效。
在我体内添加一个适当的 action
让 403 消失了。这就是解决方案。我基本上从连接和断开连接的行为中得到了 200 个响应,但是每当我的没有有效负载的消息通过时,我得到了 403。
我为 public 端点设置了 AWS API 网关,没有授权。它连接到触发 Lambda 的 websocket。
我正在与 Python 在 https://pypi.org/project/websocket_client/ 的 websocket-client
库建立连接。
我注意到大约 10% 的时间连接会失败,并且随着负载的增加而变得更糟。我找不到任何地方会限制我看到我的一般 API 网关设置说 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 日志洞察并搜索了连接 ID 和请求 ID。 API 网关的日志组找不到任何 ID 的结果。然而,在 websocket 连接上触发的对我的 Lambda 的搜索将有一个包含该连接 ID 的日志。日志显示了我们这边预期的一切 运行。 lambda 只是运行一个触发的 MySQL 查询。
为什么我会收到禁止响应,尽管 lambda 按预期工作?
getting message: forbidden reply from AWS API gateway 上的现有问题似乎解决了它是否总是返回禁止某些专用端点。没有符合我的用例的内容。
更新
我认为这可能与我每秒都在使用的 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')
更新 2
我启用了访问日志,这是一种以前没有的日志类型。我现在可以看到我的 lambda 总是毫无问题地得到 200。 403 来自一些 MESSAGE
eventType
并没有达到实际的 routeKey
。不确定它来自哪里,但很确定找到答案会解决这个问题。
我还能够确认没有 ENI 问题。
您可能 运行 遇到了一些 VPC-related 限制。参见 https://winterwindsoftware.com/scaling-lambdas-inside-vpc/。听起来您可能 运行 不再使用 ENI。您可以尝试将函数移动到不同的 VPC。 lambda 运行 的每次调用需要多长时间?你的 lambda 是用什么语言写的?
我的示例中的负载是空的。 API 被配置为使用 $request.body.action
来知道 routeKey。连接使默认 $connect
路由生效。
在我体内添加一个适当的 action
让 403 消失了。这就是解决方案。我基本上从连接和断开连接的行为中得到了 200 个响应,但是每当我的没有有效负载的消息通过时,我得到了 403。