使用AmazonSQSClient

时间:2018-12-11 15:39:51

标签: java spring-boot amazon-sqs spring-jms

所以,我在spring jms 50-100中使用了并发性,允许最大连接数达到200。一切都按预期工作,但是如果我尝试从队列中检索100k消息,我的意思是我的sqs上有10万条消息,我正在阅读它们通过spring jms正常方法。

@JmsListener
Public void process (String message) {
count++;
Println (count);
//code
 }

我在控制台中看到了所有日志,但是大约17k之后,它开始引发异常

类似的东西:aws sdk异常:端口已在使用中。

为什么我会看到此异常以及如何处理。我摆脱了吗?

我尝试在互联网上寻找它。什么都找不到。

我的设置:

并发50-100

每个任务设置消息数:50

客户确认

timestamp=10:27:57.183, level=WARN , logger=c.a.s.j.SQSMessageConsumerPrefetch, message={ConsumerPrefetchThread-30} Encountered exception during receive in ConsumerPrefetch thread,
javax.jms.JMSException: AmazonClientException: receiveMessage.
    at com.amazon.sqs.javamessaging.AmazonSQSMessagingClientWrapper.handleException(AmazonSQSMessagingClientWrapper.java:422)
    at com.amazon.sqs.javamessaging.AmazonSQSMessagingClientWrapper.receiveMessage(AmazonSQSMessagingClientWrapper.java:339)
    at com.amazon.sqs.javamessaging.SQSMessageConsumerPrefetch.getMessages(SQSMessageConsumerPrefetch.java:248)
    at com.amazon.sqs.javamessaging.SQSMessageConsumerPrefetch.run(SQSMessageConsumerPrefetch.java:207)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: com.amazonaws.SdkClientException: Unable to execute HTTP request: Address already in use: connect

更新:我一直在寻找问题,似乎正在创建新的套接字,直到每个套接字都用完为止。

我的spring jms版本应该是4.3.10

要复制此问题,只需执行上述配置,最大连接数为200,货币设置为50-100,并将40k消息推送到sqs队列。一个人可以使用https://github.com/adamw/elasticmq作为本地堆栈服务器复制到Amazon sqs。注释jms侦听器并使用soap ui负载测试,并调用发送消息以激发许多消息。仅仅因为您评论了@jmslistener批注,它就不会占用队列中的消息。看到您已发送40k消息后,请停止。取消注释@jmslistener并重新启动服务器。

更新:

DefaultJmsListenerContainerFactory factory =
                new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setDestinationResolver(new DynamicDestinationResolver());
        factory.setErrorHandler(Throwable::printStackTrace);
        factory.setConcurrency("50-100");
        factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
        return factory;

更新:

SQSConnectionFactory connectionFactory = new SQSConnectionFactory( new ProviderConfiguration(), amazonSQSclient);

更新:

客户端配置详细信息:

Protocol : HTTP
Max connections : 200

更新:

我使用了缓存连接工厂类,看来。我阅读了堆栈溢出及其官方文档,以不使用缓存连接工厂类和默认的jms侦听器容器工厂。

https://stackoverflow.com/a/21989895/5871514

它给出了我之前遇到的相同错误。

更新

我的目标是要获得500 tps,即我应该能够消耗那么多。.所以我尝试了这种方法,看来我可以达到100-200,但不超过此数量。高并发阻塞..如果您使用它..如果您有更好的解决方案来实现它..我很高兴。

**已更新**

我正在使用amazonsqsclient

1 个答案:

答案 0 :(得分:4)

饥饿的消费者

JMS客户端倾向于实现的一种可能的优化是消息消耗缓冲区或“预取”。有时可以通过消息数量或字节大小来调整此缓冲区。

这样做的目的是防止使用者每次收到消息时都去服务器,而不是批量提取多条消息。

在有许多“快速使用者”(这些库可能采取的观点)的环境中,此预取设置为较高的默认值,以最大程度地减少这些往返行程。

但是,在消息使用者较慢的环境中,这种预取可能是个问题。较慢的使用者正在阻止较快的使用者从预取的消息中消耗消息。在高度并发的环境中,这可能会迅速导致饥饿。

在这种情况下,SQSConnectionFactory有一个property for this

SQSConnectionFactory sqsConnectionFactory = new SQSConnectionFactory( new ProviderConfiguration(), amazonSQSclient);
sqsConnectionFactory.setNumberOfMessagesToPrefetch(0);

生产者的饥饿(即通过JmsTemplate

这些JMS实现通常期望通过某些中介与代理接口。这些中介实际上缓存和重用连接,或者使用池化机制重用它们。在Java EE世界中,这通常是通过Java EE服务器上的JCA适配器或其他方法来解决的。

由于Spring JMS的工作方式,它希望存在ConnectionFactory的中间代理来进行此缓存/池化。否则,当Spring JMS要连接到代理时,每次您想对代理进行操作时,它将尝试打开新的连接和会话(!)

为解决此问题,Spring提供了一些选项。最简单的是CachingConnectionFactory,它缓存单个Connection,并允许在该Session上打开许多Connection。将其添加到上面的@Configuration的简单方法是:

@Bean
public ConnectionFactory connectionFactory(AmazonSQSClient amazonSQSclient) {

    SQSConnectionFactory sqsConnectionFactory = new SQSConnectionFactory(new ProviderConfiguration(), amazonSQSclient);

    // Doing the following is key!
    CachingConnectionFactory connectionfactory = new CachingConnectionFactory();
    connectionfactory.setTargetConnectionFactory(sqsConnectionFactory);
    // Set the #connectionfactory properties to your liking here...

    return connectionFactory;

}

如果您希望将其作为JMS池解决方案的更多选择(除了多个Connections之外还将为您池MessageProducerSession),可以使用相当新的PooledJMS projectJmsPoolConnectionFactory等来自他们的库。