RabbitMQ Consumer仅消耗发送的一部分消息

时间:2017-08-20 11:13:31

标签: java rabbitmq spring-rabbit spring-rabbitmq

我向RabbitMQ发送少量消息,但消费者只消耗其中两封消息。在下面找到我的制作人和代码的代码。消费者:

@Component
public class Producer implements CommandLineRunner {

private final RabbitTemplate rabbitTemplate;
private final Consumer receiver;
private final ConfigurableApplicationContext context;

public Producer(Consumer receiver, RabbitTemplate rabbitTemplate,
        ConfigurableApplicationContext context) {
    this.receiver = receiver;
    this.rabbitTemplate = rabbitTemplate;
    this.context = context;
}

private List<Message> extractphoneNumberNumbers(String path){
    List<Message> messages = new ArrayList();
    try{
        BufferedReader fileReader = new BufferedReader(
                  new InputStreamReader(new ClassPathResource(path).getInputStream()));
        JsonReader reader = new JsonReader(fileReader);
        Gson gson = new GsonBuilder().create();
        messages = new Gson().fromJson(reader, new TypeToken<List<Message>>() {}.getType());
    }catch(Exception e){
        System.out.println(e.getMessage());
    }
    return messages;
}

public void run(String... args) throws Exception {
    List<Message> messagesToPublish = extractphoneNumberNumbers("phoneNumbers");
    AtomicInteger messageId = new AtomicInteger();
    for(Message message : messagesToPublish){
        System.out.println("Sent " + message.toString());
        rabbitTemplate.convertAndSend(App.queueName, new Message(messageId.incrementAndGet(), message.getPhoneNumber()));
    }
    receiver.getLatch().await(10000, TimeUnit.MILLISECONDS);

    context.close();
}

}


@Component
public class Consumer {
private CountDownLatch latch = new CountDownLatch(1);
private HashMap<String, Integer> phoneCountryCode = new HashMap<String, Integer>();
private int i = 0;

public void receiveJsonMessages(Message message){
    System.out.println("Received " + message.toString());
    phoneCountryCode.put(message.getCountryCode(), phoneCountryCode.getOrDefault(message.getCountryCode(), 0) + 1);

    for(Map.Entry<String, Integer> entry : phoneCountryCode.entrySet()){
        System.out.println(entry.getKey() + " " + entry.getValue());
    }

    latch.countDown();
}

public CountDownLatch getLatch() {
    return latch;
}
}
Received 5 - +40722579707 - RO
Sent 0 - +447984627687 - GB
RO 1
Received 6 - +40722579717 - RO
Sent 0 - +447984627657 - GB
RO 2
Sent 0 - +447984627667 - GB
Sent 0 - +447984627677 - GB
Sent 0 - +40722579707 - RO
Sent 0 - +40722579717 - RO
Sent 0 - +40722579727 - RO

目标是按国家/地区分组和统计电话号码。我现在只是在玩RabbitMQ,没有经验,所以分组现在......很傻。

问题是,为什么只收到两条消息,而不是7?

编辑:我认为是因为工作人员(制片人)完成后豆子停止了。如何在消费者完成后将其配置为停止?

@SpringBootApplication
public class App {
final static String queueName = "rtap-queue";

@Bean
Queue queue() {
    return new Queue(queueName, false);
}

@Bean
TopicExchange exchange() {
    return new TopicExchange("rtap-exchange");
}

@Bean
Binding binding(Queue queue, TopicExchange exchange) {
    return BindingBuilder.bind(queue).to(exchange).with(queueName);
}

@Bean
SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
        MessageListenerAdapter listenerAdapter) {
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setConnectionFactory(connectionFactory);
    container.setQueueNames(queueName);
    container.setMessageListener(listenerAdapter);
    container.setConcurrentConsumers(10);
    container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
    return container;
}

@Bean
MessageListenerAdapter listenerAdapter(Consumer receiver) {
    return new MessageListenerAdapter(receiver, "receiveJsonMessages");
}

public static void main(String[] args) throws InterruptedException {
    SpringApplication.run(App.class, args);
}
}

1 个答案:

答案 0 :(得分:0)

点击此处的示例https://www.rabbitmq.com/tutorials/tutorial-one-spring-amqp.html。重要的是

@RabbitHandler
public void receive(String in) {
    System.out.println(" [x] Received '" + in + "'");
}

该方法在场景后面的循环中运行,并在消息可用时使用消息。如果您确实要关闭上面的上下文,则需要知道要使用的消息数,并使用预期的消息数配置CountDownLatch。当您收到消息时,您可以倒计时并等待主线程中的锁存器。但是,这并不保证您将收到所有消息,没有任何保证可能发生的任何情况,例如网络故障。然后,您可以在锁定等待时配置超时。