Spring boot 读兔子mq的速度非常慢

Spring boot 读兔子mq的速度非常慢,spring-boot,rabbitmq,spring-batch,spring-rabbit,Spring Boot,Rabbitmq,Spring Batch,Spring Rabbit,我有一个作业,它必须从rabbitmq队列读取数据并将其写入数据存储。目前我正在使用AmqpItemReader从队列中读取消息 我读取的数据是Json格式的,我的ItemProcessor所做的就是将Json序列化为java对象 我的单线程解决方案的性能非常低。我只能以每秒12毫秒的速度消费。我将有大约1000万条记录需要处理。因此,我尝试将其更改为多线程步骤,但仍然无法看到吞吐量的显著提高(约为每秒50毫秒) 我将如何加快我的工作。我开始怀疑我走的路线不对。如能对此有所了解,将不胜感激。提前

我有一个作业,它必须从
rabbitmq
队列读取数据并将其写入数据存储。目前我正在使用
AmqpItemReader
从队列中读取消息

我读取的数据是Json格式的,我的
ItemProcessor
所做的就是将
Json
序列化为java对象

我的单线程解决方案的性能非常低。我只能以每秒12毫秒的速度消费。我将有大约1000万条记录需要处理。因此,我尝试将其更改为多线程步骤,但仍然无法看到吞吐量的显著提高(约为每秒50毫秒)

我将如何加快我的工作。我开始怀疑我走的路线不对。如能对此有所了解,将不胜感激。提前谢谢

编辑:包括代码/配置,以进一步明确我要实现的目标。

Rabbit服务器配置: AWS上的3节点群集,每个群集具有0.5 Gig内存

信息详情: 每个有效负载大约为1千字节JSON

我正在我的开发机器(Macintosh)上运行spring批处理作业

系统配置:

  Processor Name:   Intel Core i7
  Processor Speed:  2.5 GHz
  Number of Processors: 1
  Total Number of Cores:    4
  L2 Cache (per Core):  256 KB
  L3 Cache: 6 MB
  Memory:   16 GB
我的项目阅读器:

import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.batch.item.amqp.AmqpItemReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class RabbitMQItemReader extends AmqpItemReader<Message> {

  private final Logger logger = LoggerFactory.getLogger(RabbitMQItemReader.class);

  @Autowired
  private final RabbitTemplate template;

  public RabbitMQItemReader(RabbitTemplate rabbitTemplate) throws IOException {
    super(rabbitTemplate);
    template = rabbitTemplate;
  }

  @Override
  public Message read() {
    return template.receive();
  }
}

如果其他配置/代码有帮助,请告诉我,我也很乐意与大家分享。

嗯,
amqpmetplate.receive()
肯定非常慢。它基于
Channel.basicGet()
,它的性能不如长寿
BasicConsumer
。我建议放弃
AmqpItemReader
,转而使用Spring AMQ提供的
MessageListenerContainer
预回迁

您已经写了一个很好的投诉-但是,为了让任何人帮助您,如果您至少提供一些技术细节,可能会很好。这可能包括机器配置、兔子配置、消息大小、,以及任何其他相关细节。@我添加了配置和一点代码(如果有帮助的话)。我需要在这里澄清一些事情-基本上,Basic.Get在协议级别发送与Basic.Deliver相同的数据-因此,如果速度较慢,这一定是客户端实现的产物。实际上,拉取消息要比推送消息明智得多,除非您只是将RMQ用作一个奇特的路由器。
AmqpItemReader
基于
rabbitmplate.receive()
。打开
频道
,创建
默认消费者
,执行
basicConsume()
,等待
交付
并按倒序关闭所有内容。因此,是的,从技术上讲,我们也是这样做的,但是在
ListenerContainer
的情况下,我们经常这样做。通过
rabbitmplate.receive()
我们为每个调用打开和关闭资源。这就是性能瓶颈所在。好吧,这不是
Basic.Get
,但如果连接保持打开状态,这是一个很好的实现。
通道
只是添加到协议中的一个整数,因此在此实现中,与
Basic.Get
相比,将有一个额外的数据包通过线路发送,其代价是不需要轮询服务器。我不明白为什么这会非常昂贵,但我可以看到吞吐量可能会受到限制。消费者可能是一个更好的选择,但也有。@ArtemBilan感谢您的回复。有没有什么例子可以让我看看这条路线?我仍然希望使用现有的ItemProcessor和ItemWriter。我遇到的所有示例都有自己的tasklet来执行工作。我是否可以使用SpringBatch与MessageListenerContainer一起提供的面向块的处理能力?是的,这是一个想法,但我不知道(目前)如何实现这个解决方案。我们可以使用类似于
ItemStream
的东西,并使用所提到的
Channel.basicGet()
执行
RabbitOperations.execute()
。这样,我们将在
ItemStream.open()
中打开一个
频道
,直到
ItemStream.open()。但是需要弄清楚课堂上的流程应该是怎样的。。。
private Step step() throws Exception {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(100);
    executor.setMaxPoolSize(100);
    executor.setThreadNamePrefix("SThread");
    executor.setWaitForTasksToCompleteOnShutdown(true);

    executor.initialize();
    return stepBuilderFactory.get("queueToCassandraStep")
        .<Message, Vendor>chunk(100)
        .reader(itemReader)
        .listener(new QueueReaderListener<>())
        .processor(asyncItemProcessor())
        .writer(asyncItemWriter())
        .taskExecutor(executor)
        .build();
  }
import lombok.Setter;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConfigurationProperties("art.com.service.product.config.rabbitmq")
public class RabbitConfig {

  @Setter
  private String host;
  @Setter
  private Integer port;
  @Setter
  private String username;
  @Setter
  private String password;
  @Setter
  private String exchangeName;
  @Setter
  private String queueName;

  @Bean
  ConnectionFactory rabbitConnectionFactory() {
    CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host);
    connectionFactory.setPort(port);
    connectionFactory.setUsername(username);
    connectionFactory.setPassword(password);
    return connectionFactory;
  }

  @Bean
  public MessageConverter jsonMessageConverter() {
    return new Jackson2JsonMessageConverter();
  }

  @Bean
  RabbitTemplate rabbitTemplate(ConnectionFactory rabbitConnectionFactory,
      MessageConverter jsonMessageConverter) {

    RabbitTemplate rabbitTemplate = new RabbitTemplate(rabbitConnectionFactory);
    rabbitTemplate.setQueue(queueName);
    rabbitTemplate.setExchange(exchangeName);
    rabbitTemplate.setMessageConverter(jsonMessageConverter);

    return rabbitTemplate;
  }


}