【问题标题】:AWS ALB of a Go Lambda always returns "502 Bad Gateway"Go Lambda 的 AWS ALB 总是返回“502 Bad Gateway”
【发布时间】:2020-11-02 15:58:32
【问题描述】:

我有一个使用 Go 语言实现的 AWS Lambda。 Lambda 由 ALB 触发。当我从外部调用 ALB 时,它总是返回:

<html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
</body>
</html>

在 CloudWatch 中,我可以看到调用了 Lambda。在这个article 中,我读到 ALB 期望来自 Lambda 的非常具体的响应对象。我已经将它实现为一个结构。这是 Go Lambda 代码:

package main

import (
    "context"
    "encoding/json"
    "fmt"
    "github.com/aws/aws-lambda-go/lambda"
    "log"
)

type Request struct {
    HttpMethod string `json:"httpMethod"`
    Path string `json:"path"`
    QueryStringParameters map[string]string `json:"queryStringParameters"`
    IsBase64Encoded bool `json:"isBase64Encoded"`
    Body string `json:"body"`
    Headers RequestHeaders `json:"headers"`
}

type RequestHeaders struct {
    Accept string `json:"accept"`
    AcceptLanguage string `json:"accept-language"`
    ContentType string `json:"Content-Type"`
    Cookie string `json:"cookie"`
    Host string `json:"host"`
    UserAgent string `json:"user-agent"`
    XAmznTraceId string `json:"x-amzn-trace-id"`
    XForwardedFor string `json:"x-forwarded-for"`
    XForwardedPort string `json:"x-forwarded-port"`
    XForwardedProto string `json:"x-forwarded-proto"`
}

type Response struct {
    IsBase64Encoded bool `json:"isBase64Encoded"`
    StatusCode int `json:"statusCode"`
    StatusDescription string `json:"statusDescription"`
    Headers *ResponseHeaders `json:"headers"`
    Body string `json:"body"`
}

type ResponseHeaders struct {
    ContentType string `json:"Content-Type"`
}

func HandleRequest(ctx context.Context, request Request) (string, error) {
    fmt.Println("Hello " + request.Body)
    responseHeaders := new(ResponseHeaders)
    responseHeaders.ContentType = "application/json"
    response := new(Response)
    response.IsBase64Encoded = false
    response.StatusCode = 200
    response.StatusDescription = "200 OK"
    response.Headers = responseHeaders
    response.Body = "{\"hello\":\"world\"}"
    json, err := json.Marshal(response)
    if err != nil {
        log.Fatal(err)
    }
    responseString := string(json)
    log.Println(responseString)
    return responseString, nil
}

func main() {
    lambda.Start( HandleRequest )
}

在 Cloudwatch 中,我可以看到 Lambda 被调用,这是它返回的字符串:

{
    "isBase64Encoded": false,
    "statusCode": 200,
    "statusDescription": "200 OK",
    "headers": {
        "Content-Type": "application/json"
    },
    "body": "{\"hello\":\"world\"}"
}

据我所知,它看起来像 article 中描述的响应规范。

来自 ALB 本身的日志如下所示:

http 2020-07-13T11:49:51.014327Z app/test-Lambda/3e92b31e6a921454 176.199.208.26:54486 - 0.006 0.021 -1 502 - 736 293 "POST http://test-lambda-999999999.eu-central-1.elb.amazonaws.com:80/ HTTP/1.1" "insomnia/7.1.1" - - arn:aws:elasticloadbalancing:eu-central-1:999999999:targetgroup/test-lambda-target/540454d9390da765 "Root=1-5f0c4a5e-ca4e4a43b6c48633dc4c5b3e" "-" "-" 0 2020-07-13T11:49:50.986000Z "forward" "-" "LambdaInvalidResponse" "-" "-"

我已经在调试上投入了几个小时,但我真的不知道为什么 ALB 总是返回 502 错误。你能看到错误吗?我做错了什么?

【问题讨论】:

  • 在不使用 ALB(例如从 VPC 内部)调用 Lambda 时会看到什么?
  • 如果您将函数更改为返回(Response, error) 并跳过json.Marshal 是否有效?只要您返回可序列化的内容,该库就应该为您处理该部分。给它一个充满 JSON 的string 似乎可能会导致双重编码。
  • @hobbs:是的!那行得通!如果我直接返回 Response 结构,它就像魅力一样!你救了我的一天!非常感谢。

标签: amazon-web-services go aws-lambda aws-alb


【解决方案1】:

通过 cmets 中的调试解决:您需要从处理程序返回实际的 Response 结构,而不是包含 JSON 的字符串。 lambda 库自行处理将返回值序列化为 JSON。

【讨论】:

  • HandleRequest 的签名是这样的:func HandleRequest(ctx context.Context, request Request) (*Response, error),最后一行是这样的:return response, nil
猜你喜欢
  • 2019-09-15
  • 2019-08-24
  • 1970-01-01
  • 1970-01-01
  • 2017-07-07
  • 2020-06-14
  • 2021-02-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多