我在EC2上运行一个长时间运行的工作进程,它使用来自SQS队列的项目。过了一段时间(8-12小时,我估计)我开始得到过期的安全令牌错误。我希望aws lib能够自动处理凭证刷新,但似乎并非如此。无论如何在客户端内处理? 仅当我使用DefaultCredentialsProviderChain生成访问时才会发生这种情况。与密钥和密钥一起使用时不会发生此错误。 堆栈跟踪如下:
com.amazonaws.AmazonServiceException: The security token included in the request is expired (Service: AmazonSQS; Status Code: 403; Error Code: ExpiredToken; Request ID: 6ff6e1a0-d668-5ac5-bcd7-ae30058f25c0)
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1182)
at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:770)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:489)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:310)
at com.amazonaws.services.sqs.AmazonSQSClient.invoke(AmazonSQSClient.java:2419)
at com.amazonaws.services.sqs.AmazonSQSClient.receiveMessage(AmazonSQSClient.java:1130)
at com.amazonaws.services.sqs.AmazonSQSAsyncClient$24.call(AmazonSQSAsyncClient.java:1783)
at com.amazonaws.services.sqs.AmazonSQSAsyncClient$24.call(AmazonSQSAsyncClient.java:1779)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
我发现的解决方法是每次遇到过期的令牌错误时更新awsCredentials并重置sqs客户端。
awsCredentials = (new DefaultAWSCredentialsProviderChain).getCredentials
sqs = SimpleSQSClient(awsCredentials, Regions.US_EAST_1)
queueSQS = sqs.simple(QueueName(queueName), true)
注意:我正在使用包装器kifi/franz
答案 0 :(得分:8)
AWS软件开发工具包确实能够循环从实例配置文件继承的临时凭证,但是通过在SimpleSQSClient的构造函数中传递显式的AWSCredentials对象,我相信您拒绝这样做的机会。
您没有明确声明您的应用程序正在继承实例角色,但您的帖子中有足够的证据可以推断出这种情况:
文档中描述了自动凭据刷新的特定行为:
只有在使用时才会自动刷新凭据 默认客户端构造函数,它自己创建 InstanceProfileCredentialsProvider作为默认提供程序的一部分 链,或者当您传递InstanceProfileCredentialsProvider实例时 直接到客户端构造函数。如果你使用另一种方法 获取或传递实例配置文件凭据,您负责 检查并刷新过期的凭据。
通过直接传递AWSCredentials而不是AWSCredentialsProvider,您将负责检查和刷新过期的凭据。从好的方面来说,如果您想要明确地传递凭据,那么您的解决方法就可以了。
SimpleSQSClient有一个构造函数,可以更好地适用于您的用例:
new SimpleSQSClient(
credentialProvider: com.amazonaws.auth.AWSCredentialsProvider,
region: com.amazonaws.regions.Regions,
buffered: Boolean
)
示例:
SimpleSQSClient sqs = SimpleSQSClient(new DefaultAWSCredentialsProviderChain(), Regions.US_EAST_1, false)
示例,明确使用InstanceProfileCredentialsProvider:
SimpleSQSClient sqs = SimpleSQSClient(new InstanceProfileCredentialsProvider(), Regions.US_EAST_1, false)
进一步阅读: