websocket 在AWS lambda和API网关上调用post_to_connection时出现GoneException

tzxcd3kk  于 2023-06-23  发布在  Go
关注(0)|答案(4)|浏览(173)

我想在WebSocket客户端连接到AWS lambda和API网关上的服务器时向其发送消息。目前,我使用wscat作为客户端。由于当我连接到服务器时,wscat控制台上没有显示响应'connected',所以我添加了post_to_connection来向客户端发送消息'hello world'。但是,它会引发GoneException。
调用PostToConnection操作时出错(GoneException)
如何解决这个问题,并在连接到服务器时向wscat发送一些消息?
下面是我的Python代码。我使用Python 3.8.5。

import os
import boto3
import botocore

dynamodb = boto3.resource('dynamodb')
connections = dynamodb.Table(os.environ['TABLE_NAME'])

def lambda_handler(event, context):
    domain_name = event.get('requestContext',{}).get('domainName')
    stage       = event.get('requestContext',{}).get('stage')
    connection_id = event.get('requestContext',{}).get('connectionId')
    result = connections.put_item(Item={ 'id': connection_id })

    apigw_management = boto3.client('apigatewaymanagementapi',
                            endpoint_url=F"https://{domain_name}/{stage}")
    ret = "hello world";

    try:
      _ = apigw_management.post_to_connection(ConnectionId=connection_id,
                                             Data=ret)
    except botocore.exceptions.ClientError as e:
      print(e);
      return { 'statusCode': 500,
                    'body': 'something went wrong' }

    return { 'statusCode': 200,
             "body": 'connected'};
kg7wmglp

kg7wmglp1#

自我回答:你不能在onconnect中post_to_connection到连接本身。

gijlo24d

gijlo24d2#

我发现,当启动websocket的客户端与socket断开连接并且无法再找到其connectionId时,可能会发生GoneException。是否有什么原因导致原始客户端在接收到您的返回消息之前与套接字断开连接?
我的用例是不同的,但我基本上是使用DB来检查连接的状态,然后再回复它,而不是使用请求上下文来做这件事。通过在连接时将connectionIds写入DynamoDB,并在发生断开连接事件时将其从表中删除,可以减少此错误的出现。消息传递现在写入表中的connectionIds,而不是请求上下文中的id。大多数消息都能通过,但当客户端离开套接字但没有发出适当的断开连接事件时,仍然会发出一些错误,这会在表中留下孤儿。下一步是在发生不规则断开时强制删除项。对于您的情况来说,涉及DB可能有点过头了,只是分享一下帮助我在GoneException错误上取得进展的东西。

zysjyyx4

zysjyyx43#

我们需要在连接后发布到连接(即当routeKey不是$connect时)

routeKey = event.get('requestContext', {}).get('routeKey')
print(routeKey)  # for debugging 

if routeKey != '$connect':  # if we have defined multiple route keys we can choose the right one here
  apigw_management.post_to_connection(ConnectionId=connection_id, Data=ret)
nkoocmlb

nkoocmlb4#

@nemy的回答是完全正确的,但它没有解释原因。所以,我只想解释一下...
什么是GoneException或GoneError 410?
当用户尝试访问请求的服务器上不再存在的资产时,会发生410 Gone错误。为了使请求返回410 Gone状态,资源也必须没有转发地址,并被认为是永久消失的。
您可以在本文中找到有关GoneException的更多详细信息。
在这里,发生了GoneException;这意味着我们尝试建立的POST连接不存在-这完全符合场景。因为我们还没有建立客户端和服务器之间的连接。APIGatewayWebsocketAPI的工作方式是,您请求一个端点(Route),该端点将调用该Lambda函数(在我们的示例中,它是$connect Route的ConnectionLambda函数)。
现在,如果Lambda函数解析为statusCode: 200,则API网关将允许建立连接。所以,基本上直到我们从Lambda函数返回statusCode: 200,我们都没有连接,直到那时我们对服务器是完全未知的,这就是为什么在return语句本身之前进行的Post调用会抛出错误。

相关问题