我们有几个lambda函数,我已经使用gradle-aws-plugin-reboot插件自动化了代码部署。
除了一个 * lambda函数外,它在所有 * lambda函数上都很好用。在那个特定的函数上,我得到了这个错误:
com.amazonaws.services.lambda.model.ResourceConflictException: The operation cannot be performed at this time. An update is in progress for resource: arn:aws:lambda:*redacted*:the-lambda-that-fails (Service: AWSLambda; Status Code: 409; Error Code: ResourceConflictException; Request ID: 8fef505a-587c-4e77-a257-182d6eecadd0; Proxy: null)
不过,对于这个错误还有一个额外的警告:这种情况只发生在Jenkins上。从我的本地机器运行部署任务是有效的。我可以通过快速连续地发送垃圾邮件来在本地重现这个问题,在这种情况下,每隔一秒就有一个失败。考虑到错误消息,这是可以理解的。
有趣的是,虽然它失败的原因和jenkins一样,但它并不是在同一个点失败的。当我在本地这样做时,它在部署环境时失败,而在jenkins上,它在部署代码时总是失败。我不确定插件先做哪一个。另外,在jenkins上它并不总是失败,甚至这个lambda的部署成功的例子也很少,但是没有任何其他失败的例子。
我知道新的lambda states feature,它可能会产生这个错误,但是,因为所有其他的lambdas工作,在build.gradle和jenkinsfile中使用相同的代码,这似乎不太可能是我的问题。
以下是gradle中的部署任务:
register<jp.classmethod.aws.reboot.gradle.lambda.AWSLambdaMigrateFunctionTask>("deploy") {
// Create the environment variables from the gradle property configuration.
// users and passwords should be stored in the system properties file, not the projects!
val (environmentProperties, function) = if (branch == "master") {
val webcamServicePutterProd: String by project
val webcamServicePutterProdPwd: String by project
mapLambdaProperties("deployProd_", webcamServicePutterProd, webcamServicePutterProdPwd) to
"lambda-function-name-prod"
} else {
val webcamServicePutterDev: String by project
val webcamServicePutterDevPwd: String by project
mapLambdaProperties("deployDev_", webcamServicePutterDev, webcamServicePutterDevPwd) to
"lambda-function-name-dev"
}
val jarFile = File("build/libs").walk().first { it.name.endsWith("-all.jar") }
functionName = function
zipFile = jarFile
handler = "webcam.yellow.sqs.lambda.WebcamWorker::handleRequest"
publish = true
environment = environmentProperties
}
如前所述,这在所有的lambdas中几乎是相同的,除了属性,显然,属性也不是问题所在,因为它们在我的本地环境和jenkins中是相同的。
jenkinsfile中的部署执行非常普通,它首先将jar上传到S3进行归档,然后执行gradle任务部署lambda。为了确保安全,我尝试不使用S3上传,以防可能存在一些模糊的连接,但这也没有帮助。
stage('Deploy artifact') {
when {
equals expected: 'true', actual: deployArtifact
}
steps {
// archive build on S3
withAWS() {
s3Upload(
workingDir: 'build/libs/',
includePathPattern: '*-all.jar',
bucket: 'yellow-artifacts',
path: "webcam-worker-lambda/${artifactFolder}/"
)
}
// deploy build to lambda
sh './gradlew deploy'
}
}
我花了几个小时检查不同lambdas的所有配置,比较它们,寻找可能是问题根源的差异,但我现在几乎不知道问题可能出在哪里。有人有什么预感吗?
3条答案
按热度按时间lf5gs5x21#
我明白了。你最好别把东西含在嘴里,因为这太搞笑了!
基本上是所有的选择,我锁定了最后一个明显的差异,这个部署和工作:正在部署的jar的文件大小。失败的那个是目前为止最小的。所以我把它膨胀了大约60%,使它可以与其他任何东西相比...这样就修复了它!
这听起来很荒谬。下面是我的假设:如果上传花费的时间太少,lambda不知何故需要更长的时间来改变它的状态。我不知道为什么会这样,你会期望状态在事情 * 完成 * 时改变,而不是在事情做得更快时花费更长的时间,对吗?也许存在状态保持的最短时间?我不知道。不过,有一件事支持这个假设:从我的本地电脑部署总是有效的,上传的时间自然比jenkins从aws vpc内部所需的时间要长,所以这个假设,听起来很可笑,符合我手头上的所有事实。
也许对lambda内部机制有更好理解的人可以添加一个注解来解释这是如何发生的...
luaexgnf2#
在我的例子中,我在Lambda的描述中添加了
aws:states:opt-out
后,它就解决了,如下所述:https://aws.amazon.com/de/blogs/compute/coming-soon-expansion-of-aws-lambda-states-to-all-functions/lhcgjxsq3#
ResourceConflictException表示资源已存在,或者正在进行另一个操作
如果上一个配置更新尚未完成,则无法调用Lambda函数或再次修改它。如果您执行了创建或修改函数等操作,并且在此之后不久,由于上一个操作,该函数仍处于“暂挂”状态,则可能会遇到此错误。以下是有关此错误的简短说明。
GetFunctionConfiguration响应中的LastUpdateStatus、LastUpdateStatusReason和LastUpdateStatusReasonCode字段指示更新何时完成以及函数何时使用新配置处理事件。有关详细信息,请参阅Lambda function states。