我正在尝试使用java sdk访问亚马逊队列。队列设置在具有EC2实例角色的环境中,因此我不需要使用凭据来访问它。 这是我的代码
public AWSSimpleQueueServiceClient(String queueName, String endPoint) {
try{
this.queueName = queueName;
logger.debug("Queue Name = " + this.queueName + "Endpoint = " + endPoint);
this.sqs = new AmazonSQSClient(new InstanceProfileCredentialsProvider());
if(endPoint != null) {
this.sqs.setEndpoint(endPoint);
}
} catch (Exception e) {
logger.error("Exception while creating AWS SQS Client = " + e.getMessage());
}
}
从配置文件中获取QueueName和Endpoint。 我尝试从队列发送/接收消息,但它给了我以下异常
Exception in thread "main" com.amazonaws.services.sqs.model.QueueDoesNotExistException: The specified queue does not exist or you do not have access to it. (Service: AmazonSQS; Status Code: 400; Error Code: AWS.SimpleQueueService.NonExistentQueue; Request ID: c30b2c9a-0e62-560d-9306-628ebff676d8)
at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1160)
at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:748)
at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:467)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:302)
at com.amazonaws.services.sqs.AmazonSQSClient.invoke(AmazonSQSClient.java:2422)
at com.amazonaws.services.sqs.AmazonSQSClient.getQueueUrl(AmazonSQSClient.java:541)
at com.ensighten.inform.sqsClient.AWSSimpleQueueServiceClient.getQueueUrl(AWSSimpleQueueServiceClient.java:66)
但是,当我尝试使用curl命令访问队列时,我收到了响应
aws sqs receive-message --queue-url <Endpoint>/031143137427/<QueueName> -- region us-east-1
{
"Messages": [
{
"Body": "Test",
"ReceiptHandle": "AQEBA49LjMDLPyyl4QKwHx9/oVFDV7mZDiOOpdKS/IC2zR3GNblg2IoHuqWBgr5iw7URCkL03Dm23TCs0Z2hB2DIzU+9qxZTOa9Ti57eiHOyAL2XAlbk7TAqGCR4lcsdSW8+LJ5zWCTkBUg5iZOqy4P0KFTfI7KtJJb2aAmeWJpApu+yJRTNAkYtdN91EcYOVFHqc1p6HJmtvvW6vJwfHB5JEbagXdfWwH3/UnJ/O36JwuFoLDp/NBRu6TO+bmYxeZmCN4GdhHuT0a11weki6Ez47Ln63G11LeQ4SFdZTC7QOWflypf8FSbG8W4JGGPZ8J8iWTkW7PGGw6DRavSu97rx3w==",
"MD5OfBody": "1f871ceacd9f4028ed371e91400efe80",
"MessageId": "0f6290d2-4554-4d96-8f93-7564ef667feb"
}
]
}
当我在具有EC2角色的另一台机器设置上尝试时,这是一个例外。
Exception in thread "main" com.amazonaws.AmazonClientException: Unable to load credentials from Amazon EC2 metadata service
at com.amazonaws.auth.InstanceProfileCredentialsProvider.handleError(InstanceProfileCredentialsProvider.java:244)
at com.amazonaws.auth.InstanceProfileCredentialsProvider.loadCredentials(InstanceProfileCredentialsProvider.java:225)
at com.amazonaws.auth.InstanceProfileCredentialsProvider.getCredentials(InstanceProfileCredentialsProvider.java:124)
at com.amazonaws.services.sqs.AmazonSQSClient.invoke(AmazonSQSClient.java:2413)
at com.amazonaws.services.sqs.AmazonSQSClient.getQueueUrl(AmazonSQSClient.java:541)
at com.ensighten.inform.sqsClient.AWSSimpleQueueServiceClient.getQueueUrl(AWSSimpleQueueServiceClient.java:74)
at com.ensighten.inform.sqsClient.AWSSimpleQueueServiceClient.getMessagesFromQueue(AWSSimpleQueueServiceClient.java:93)
at com.ensighten.inform.jobRunner.TestJobRunner.execute(TestJobRunner.java:96)
at com.ensighten.inform.jobRunner.TestJobRunner.main(TestJobRunner.java:90)
Caused by: java.net.SocketTimeoutException: connect timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at sun.net.NetworkClient.doConnect(NetworkClient.java:175)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:432)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:527)
at sun.net.www.http.HttpClient.<init>(HttpClient.java:211)
at sun.net.www.http.HttpClient.New(HttpClient.java:308)
at sun.net.www.http.HttpClient.New(HttpClient.java:326)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:996)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:932)
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:850)
at com.amazonaws.internal.EC2MetadataClient.readResource(EC2MetadataClient.java:90)
at com.amazonaws.internal.EC2MetadataClient.getDefaultCredentials(EC2MetadataClient.java:55)
at com.amazonaws.auth.InstanceProfileCredentialsProvider.loadCredentials(InstanceProfileCredentialsProvider.java:186)
... 7 more
这是我获取队列URL的方式。尝试过两种方式。它与上述异常错误
public String getQueueUrl() {
GetQueueUrlRequest queueUrlRequest = new GetQueueUrlRequest(this.queueName);
logger.debug("Queue Name... = " + this.queueName);
//FIRST WAY -----------> EXCEPTION on the line below
System.out.println("Queue URL .....= " + this.sqs.getQueueUrl(this.queueName));
//SECOND WAY
return this.sqs.getQueueUrl(queueUrlRequest).getQueueUrl();
}
我一直试图解决这个问题。任何帮助表示赞赏。
答案 0 :(得分:-1)
当您尝试访问不再存在的SQS队列或者您没有访问它的权限时,会发生类似的问题。
正如您在问题中提到的那样,当通过AWS CLI发出curl命令时,SQS队列可以正常工作。这是一种很好的调试方法,可以确定它是否可以通过CLI在本地运行。
下一步是检查您的EC2实例是否具有所需的必要权限。根据AWS的建议,切勿在EC2实例中使用凭证或密钥秘密值来访问AWS中的其他资源。最好的方法是使用 IAM角色。根据您的问题,您需要向您的特定角色授予权限,才能访问AWS SQS资源。然后,AWS将允许在EC2实例上运行的应用程序从SQS获取消息。
此documentation提供了有关可以分配给角色的必要权限的详细信息。