【问题标题】:AWS Lambda@Edge Nodejs "Environment variables are not supported."AWS Lambda@Edge Nodejs“不支持环境变量。”
【发布时间】:2019-07-16 15:35:29
【问题描述】:

首先采用这种方法的动机来自亚马逊:https://aws.amazon.com/blogs/compute/resize-images-on-the-fly-with-amazon-s3-aws-lambda-and-amazon-api-gateway/(在他们添加“更新”之前...)

在我们的 AWS Lambda 调整大小函数中,它调整图像大小并将新图像存储在 S3 上。

const s3_bucket = process.env.s3_bucket;
S3.putObject({
  Body: buffer,
  Bucket: s3_bucket,
  ContentType: contentType,
  CacheControl: 'max-age=31536000',
  Key: key,
  StorageClass: 'STANDARD'
}).promise()

现在我们希望它适用于我们所有的测试/暂存环境以及生产环境。所以我找到了“环境变量”,我觉得很棒!但是当我尝试部署一个新版本时,我得到的只是:

我们是否在 CloudFront 中设置了错误?我们使用的是 Node 6.10 版本。我很难相信我们是否必须对存储桶进行硬编码并保留不同版本的代码来处理这个问题?如果是这样,那么我们在使用 AWS Lambda 时浪费了很多时间......

编辑:我们所做的是请求一个图像,如“media/catalog/product/3/0/30123/768x/lorem.jpg”,然后我们使用位于的原始图像在“media/catalog/product/3/0/30123.jpg”,如果浏览器支持,将其大小调整为 768px 和 webp,然后返回新图像(如果尚未缓存)。

【问题讨论】:

  • 为什么投反对票?该选项在管理员中可用,它并没有说它在您按下部署之前不起作用,那时我已经在我的代码中实现了它,将它上传到 s3 .. 花了至少一个小时..

标签: amazon-web-services environment-variables aws-lambda-edge


【解决方案1】:

使用自定义原始标头的解决方法

Lambda@Edge 不支持指定的in the limitations documentation 环境变量。

但是,如果您在源请求或源响应中使用 Lambda@Edge,则可以使用CloudFront Origin Custom Headers 的解决方法。

基本上,您可以在 CloudFront 源中设置自定义标头,而不是环境变量。然后,这些“静态”标头将传递给您的原始请求/响应 Lambda@Edge。

然后您可以通过以下方式在您的 Lambda@Edge 函数代码中访问它们:

const foo = request.origin.custom.customHeaders["x-env-foo"][0].value;

或者当使用 S3 作为原点时:

const foo = request.origin.s3.customHeaders["x-env-foo"][0].value;

另见https://medium.com/@mnylen/lambda-edge-gotchas-and-tips-93083f8b4152

【讨论】:

  • 好主意!我试试这个,但不知何故我的 customHeaders 是空的,即使我将它们设置在云端。我也尝试将它们添加到缓存策略中,但我无法使其工作:无论我的设置如何,lambda 事件对象上的 customHeaders 始终为空。
【解决方案2】:

作为所选答案的替代方案...

同样可以使用Serverless FrameworkWebpackserverless-webpack 插件来实现。

您可以通过以下方式访问用于无服务器操作的选项:

const slsw = require('serverless-webpack');
const stage = slsw.lib.options.stage;

或者,您可以通过以下方式访问serverless.yml 文件中的信息:

const serverless = slsw.lib.serverless;

然后只需将其添加到您的 webpack.config.js 文件的插件中:

plugins: [new EnvironmentPlugin({ VAR1: var1, VAR2: var2, STAGE: stage })]

此方法可以为您提供一种在 Lambda@Edge 函数中管理环境变量的简单方法 - 阅读 case studies 以了解无服务器框架为何如此出色。

【讨论】:

    【解决方案3】:

    this documentation for CloudFront Lambda limitations:中提到的

    不支持环境变量。

    您可以改为使用 SSM Parameter Store 来管理函数的变量。您可以通过控制台或programmatically编辑Parameter Store变量,您可以使用ssm.getParameter() function获取变量

    【讨论】:

    • 我真的很讨厌 lambda.. 我从未见过如此不直观、困难且耗时的工具.. 但谢谢,我会尝试的!刚刚花了一个多星期来实现这个..我已经厌倦了..
    • 如果不支持,为什么还要在界面中显示环境变量?只是为了浪费人们的时间?
    • 环境变量仅在 Lambda@Edge 中不受支持。在常规函数中,通常支持它们。你真的需要使用 Lambda@Edge 吗?普通的 Lambda 不能解决问题?
    • 我的意思是,它是一个由 S3Event 触发的调整大小函数,它本质上是异步且最终一致的。为什么要让 Lambda@Edge 来实现这一目标?
    • 我不确定我是否完全理解这个答案 :( 好的,我可以在那里存储一些东西,我可以获取它.. 但是它如何帮助确定当前请求是来自暂存还是例如生产?他们也可以有并发请求..
    【解决方案4】:

    使用 lambda 函数名称的解决方法

    如果您碰巧有针对您的开发/产品的单独功能,您也可以查看process.env.AWS_LAMBDA_FUNCTION_NAME

    const getIsDev = () => {
        // lambda at edges cant set environment variables in the console.
        if (!process.env.AWS_LAMBDA_FUNCTION_NAME) {
            return true // << double check this is the behavior you want to fall back to.
        }
        if (process.env.AWS_LAMBDA_FUNCTION_NAME.indexOf("-dev") => 0) {
            // does the function name contain the word -dev?  
            return true
        }
        return false
    }
    

    【讨论】:

      【解决方案5】:

      我将此作为评论,但我认为值得将其添加为答案。

      为什么需要先使用 Lambda@Edge?我理解您的沮丧,但 Lambda@Edge 旨在实现一组完全不同的事情。查看一些用例here

      在您的使用案例中,您将对象上传到 S3,PUT 对象事件将触发您的 Lambda 函数,该函数本质上是异步且最终一致的。您的用户真的不需要优化的缩略图生成执行时间,因为无论如何您只会获得几百毫秒。当他们需要缩略图时,无论如何它已经在那里了。

      在常规的 Lambda 函数中,您绝对可以使用环境变量,从而非常容易地将不同的设置应用于不同的环境(开发、测试、生产)。

      您可以查看如何在常规 Lambda 函数中设置环境变量here

      【讨论】:

      • 说实话我不知道。我们所做的是请求一个图像,如“media/catalog/product/3/0/30123/768x/lorem.jpg”,然后我们使用位于“media/catalog/product/3/0/”的原始图像30123.jpg”,如果浏览器支持,将其大小调整为 768px 和 webp,然后返回新图像(如果尚未缓存) - 我们不需要 @Edge 吗?
      • 我认为您的应用程序可以让我更加主动而不是被动。为什么不触发上传时调整大小?然后,您的应用程序在请求生命周期内无需处理任何内容,从而为最终用户提供更快的速度。你能告诉我这张图片是什么时候上传的吗?是用户决定缩略图的大小还是预先定义的应用程序规则?如果用户决定,我建议异步处理调整大小并返回类似:'您的请求正在处理中。它将很快可用”,然后您的前端可以对其进行轮询
      • 一般来说,根据用户请求进行图像处理并不是一个好主意,因为它通常需要相当长的时间。如果我说的对你有意义,请告诉我。希望对您有所帮助!
      • 如果您的目标是根据用户的请求进行图像处理,那么您也可以只拥有一个 API 网关 -> Lambda,这样您就可以使用环境变量。但是,Lambda edge 中缺少 env 变量并不是真正的缺点,因为如前所述,您可以使用 Parameter Store 来实现这一点(并且可以使用 node-cache 等模块来实现所述参数的缓存以节省处理时间)
      • aws.amazon.com/blogs/compute/… "动态处理图像的方法不是在上传时将图像处理和调整为所有必要的大小,而是有几个优点: 提高敏捷性 降低存储成本 抵御故障"
      【解决方案6】:

      我通过在 bash 构建脚本中的 js 文件前添加 s3_bucket 解决了这个问题。所以我指定build.sh [s3_bucket] [environment-name]

      if [ ! $# -eq 2 ]; then
          echo 'You need to provide two parameters: [s3_bucket] [environment]'
          echo 'example: build.sh imagetest-us-east-1 next'
          echo 'example: build.sh [s3_bucket_to_be_defined] production'
          exit 1
      fi
      
      filename='index.js'
      setCurrentEnvironment() {
          jsEnv="const s3_bucket='$1';"
          mv "$filename" "$filename".orig && cp "$filename".orig "$filename"
          echo -e "$jsEnv\n\n$(cat ${filename})" > "$filename"
      }
      restoreDefault() {
          rm -rf "$filename"
          mv "$filename".orig "$filename"
      }
      
      setCurrentEnvironment $1
      zip -FS -q -r "../../dist/resize__$2.zip" *
      restoreDefault
      

      【讨论】:

        猜你喜欢
        • 2018-09-14
        • 2017-12-17
        • 2018-07-07
        • 1970-01-01
        • 2021-01-14
        • 2017-08-01
        • 1970-01-01
        • 2017-04-17
        • 1970-01-01
        相关资源
        最近更新 更多