go之无法进行查询API调用,ResourceNotFoundException:无法对不存在的表执行操作

jiqing9006 阅读:118 2025-06-02 22:19:02 评论:0

概要

我通过aws lambda使AWS SAM函数。
此功能需要数据库,因此我选择DynamoDB
现在,我为AWS SAMDynamoDB设置本地环境。
看来我成功设置了本地DynamoDB,但是运行本地aws sam函数时却无法连接。

failed to make Query API call, ResourceNotFoundException: Cannot do operations on a non-existent table 

我想知道如何解决这个问题。

试过了

我创建了本地表并检查了要插入的测试数据。
❯ aws dynamodb create-table --cli-input-json file://test/positive-line-bot_table.json --endpoint-url http://localhost:8000 
TABLEDESCRIPTION        1578904757.61   0       arn:aws:dynamodb:ddblocal:000000000000:table/PositiveLineBotTable       PositiveLineBotTable    0       ACTIVE 
ATTRIBUTEDEFINITIONS    Id      N 
BILLINGMODESUMMARY      PROVISIONED     0.0 
KEYSCHEMA       Id      HASH 
PROVISIONEDTHROUGHPUT   0.0     0.0     0       5       5  
 
❯ aws dynamodb batch-write-item --request-items file://test/positive-line-bot_table_data.json --endpoint-url http://localhost:8000 
 
❯ aws dynamodb list-tables --endpoint-url http://localhost:8000 
TABLENAMES      PositiveLineBotTable 
 
❯ aws dynamodb get-item --table-name PositiveLineBotTable --key '{"Id":{"N":"1"}}' --endpoint-url http://localhost:8000 
ID      1 
NAME    test 

但是,当我在本地运行 aws sam时,尽管此表确实在本地退出,但似乎没有连接到此本地 DynamoDB
❯ sam local start-api --env-vars test/env.json 
Fetching lambci/lambda:go1.x Docker container image...... 
Mounting /Users/jpskgc/go/src/line-positive-bot/positive-line-bot as /var/task:ro,delegated inside runtime container 
START RequestId: c9f19371-4fea-1e25-09ec-5f628f7fcb7a Version: $LATEST 
failed to make Query API call, ResourceNotFoundException: Cannot do operations on a non-existent table 
Function 'PositiveLineBotFunction' timed out after 5 seconds 
Function returned an invalid response (must include one of: body, headers, multiValueHeaders or statusCode in the response object). Response received:  
2020-01-13 18:46:10 127.0.0.1 - - [13/Jan/2020 18:46:10] "GET /positive HTTP/1.1" 502 - 
❯ curl http://127.0.0.1:3000/positive 
{"message":"Internal server error"} 

我想知道如何实际连接到本地 DynamoDB表。

一些代码

这是Go中的功能代码。

package main 
 
//import 
 
func exitWithError(err error) { 
    fmt.Fprintln(os.Stderr, err) 
    os.Exit(1) 
} 
 
type Item struct { 
    Key  int 
    Desc string 
    Data map[string]interface{} 
} 
 
type Event struct { 
    Type       string  `json:"type"` 
    ReplyToken string  `json:"replyToken"` 
    Source     Source  `json:"source"` 
    Timestamp  int64   `json:"timestamp"` 
    Message    Message `json:"message"` 
} 
 
type Message struct { 
    Type string `json:"type"` 
    ID   string `json:"id"` 
    Text string `json:"text"` 
} 
 
type Source struct { 
    UserID string `json:"userId"` 
    Type   string `json:"type"` 
} 
 
func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { 
 
 
    endpoint := os.Getenv("DYNAMODB_ENDPOINT") 
    tableName := os.Getenv("DYNAMODB_TABLE_NAME") 
 
    sess := session.Must(session.NewSession()) 
 
    config := aws.NewConfig().WithRegion("ap-northeast-1") 
    if len(endpoint) > 0 { 
        config = config.WithEndpoint(endpoint) 
    } 
 
    svc := dynamodb.New(sess, config) 
 
    params := &dynamodb.ScanInput{ 
        TableName: aws.String(tableName), 
    } 
 
    result, err := svc.Scan(params) 
    if err != nil { 
        exitWithError(fmt.Errorf("failed to make Query API call, %v", err)) 
    } 
 
    items := []Item{} 
 
    err = dynamodbattribute.UnmarshalListOfMaps(result.Items, &items) 
    if err != nil { 
        exitWithError(fmt.Errorf("failed to unmarshal Query result items, %v", err)) 
    } 
 
    var words []string 
    for i, item := range items { 
        for k, v := range item.Data { 
            words = append(words, v.(string)) 
        } 
    } 
 
    rand.Seed(time.Now().UnixNano()) 
    i := rand.Intn(len(words)) 
    word := words[i] 
 
    return events.APIGatewayProxyResponse{ 
        Body:       word, 
        StatusCode: 200, 
    }, nil 
} 
 
func main() { 
    lambda.Start(handler) 
} 
 

这是 env.json我尝试将docker.for.mac.host.internal更改为我的本地IP地址。但这并不能解决。
{ 
  "PositiveLineBotFunction": { 
    "DYNAMODB_ENDPOINT": "http://docker.for.mac.host.internal:8000", 
    "DYNAMODB_TABLE_NAME": "PositiveLineBotTable" 
  } 
} 
 

这是 template.yml
AWSTemplateFormatVersion: '2010-09-09' 
Transform: AWS::Serverless-2016-10-31 
Description: > 
  positive-line-bot 
 
Globals: 
  Function: 
    Timeout: 5 
 
Resources: 
  PositiveLineBotFunction: 
    Type: AWS::Serverless::Function  
    Properties: 
      CodeUri: positive-line-bot/ 
      Handler: positive-line-bot 
      Runtime: go1.x 
      Policies: 
        - DynamoDBReadPolicy: 
          TableName: !Ref PositiveLineBotTable 
      Tracing: Active 
      Events: 
        CatchAll: 
          Type: Api  
          Properties: 
            Path: /positive 
            Method: GET 
      Environment:  
        Variables: 
          DYNAMODB_ENDPOINT: '' 
          DYNAMODB_TABLE_NAME: '' 
 
  PositiveLineBotTable: 
    Type: AWS::DynamoDB::Table 
    Properties: 
      TableName: 'PositiveLineBotTable' 
      AttributeDefinitions: 
        - AttributeName: 'Id' 
          AttributeType: 'N' 
      KeySchema: 
        - AttributeName: 'Id' 
          KeyType: 'HASH' 
      ProvisionedThroughput: 
        ReadCapacityUnits: '5' 
        WriteCapacityUnits: '5' 
      BillingMode: PAY_PER_REQUEST 
 
Outputs: 
  PositiveLineBotAPI: 
    Description: 'API Gateway endpoint URL for Prod environment for PositiveLineBot' 
    Value: !Sub 'https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/positive/' 
  PositiveLineBotFunction: 
    Description: 'PositiveLineBot Lambda Function ARN' 
    Value: !GetAtt PositiveLineBotFunction.Arn 
  PositiveLineBotFunctionIamRole: 
    Description: 'Implicit IAM Role created for PositiveLineBot' 
    Value: !GetAtt PositiveLineBotFunction.Arn 

这是完整的源代码。
https://github.com/jpskgc/line-positive-bot

请您参考如下方法:

参见this answer

解决方案包括两部分:

  • 创建一个docker-network并使用该网络启动dynamodb-local容器和api
  • 适当调整端点。

  • 对我来说,我做到了:
    docker network create dynamodb-network 
    docker run -d -v "$PWD":/dynamodb_local_db -p 8000:8000 --network dynamodb-network --name dynamodb cnadiminti/dynamodb-local 
    sam local start-api --docker-network dynamodb-network -n env.json 
    

    在我的代码中,我引用了docker名称作为DNS地址:
    const awsRegion = process.env.AWS_REGION || "us-east-2"; 
    const options = { 
      region: awsRegion, 
    }; 
    if (process.env.AWS_SAM_LOCAL) { 
      options.endpoint = "http://dynamodb:8000"; 
    } 
    const docClient = new dynamodb.DocumentClient(options); 
    


    标签:Exception
    声明

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    关注我们

    一个IT知识分享的公众号