仅在队列中达到限制后,才触发侦听器使用消息

时间:2019-08-24 18:14:28

标签: rabbitmq spring-integration spring-rabbitmq spring-integration-amqp

我正在使用Order请求的Collection,每个请求都有一个标识符和order_id列表(例如abc123,def456、789ghl..so等)。基本上,集合可以包含4种类型的订单,我有4个API分别获取它们的“订单状态”。我的要求是实现队列机制,并将这些请求发送到相应的API,然后使用Spring Boot将响应发送回调用方。共有4个约束:

  1. 所有API应该有一个单独的队列。
  2. 仅在队列中达到限制10后才将请求转发到API,即直到9将保留请求并将第十个请求发送到API。在任何时候9将进入队列。
  3. 如果满足上述条件,那么我必须为任何特定的API调用发送大量10个order_id。
  4. 只有在收到来自所有查询到的API端点的响应之后,才应响应原始服务请求。

我正在为此目的实现Spring amqp和RabbitMq。

任何人都可以建议该方法或如何实施此方法吗?我无法实现第二,第三和第四约束。

@服务 公共类ShipmentListener {

private static final Logger log = LoggerFactory.getLogger(ShipmentListener.class);

@Autowired
private RestTemplate restTemplate;

@Autowired
private ApplicationConfigReader appConfigReader;

@Autowired
ApiMessageRequestBufferGenerator shipmentBuffer;

private final CountDownLatch latch = new CountDownLatch(5);

@RabbitListener(queues = "${shipment.queue.name}")
public Map<String, List<String>> shipmentConsumer(final MessageRequest message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
    log.info("Received message: {} from shipment queue.", message);
    Optional<List<MessageRequest>> optMessageRequest = shipmentBuffer.getMessageRequestBuffer().add(message);

    if (optMessageRequest.isPresent()) {
        Map<String, List<String>> test = new HashMap<String, List<String>>();
        List<MessageRequest> listRequest = optMessageRequest.get();
        for (List<String> request : createApiBulkRequestData(listRequest)) {
            test.putAll(callShipmentAPI(request));
        }
        return test;
    }
    channel.basicAck(tag, false);
    latch.countDown();
    return null;
}

private List<List<String>> createApiBulkRequestData(List<MessageRequest> listOfRequest) {
    List<List<String>> listOLists = new ArrayList<List<String>>();
    List<String> allQueryParam = listOfRequest.stream()
                                            .map(value -> value.getQueryParam())
                                            .map(map -> map.entrySet())
                                            .flatMap(each -> each.stream())
                                            .map(m -> m.getKey())
                                            .collect(Collectors.toList());
    int counter = 1;
    List<String> values = new ArrayList<>();
    while (counter < allQueryParam.size()) {
        values.add(allQueryParam.get(counter++));
        if (counter % 5 == 0) {
            listOLists.add(values);
            values = new ArrayList<>();
        }
    }

    if(values.size() < 0 && values.size() < 5) {
        listOLists.add(values);
    }

    return listOLists;
}

private Map<String, List<String>> callShipmentAPI(List<String> message) {
    ParameterizedTypeReference<Map<String, List<String>>> typeRef = null;
    ResponseEntity<Map<String, List<String>>> response = null;
    HttpEntity<String> requestEntity = new HttpEntity<>(buildRequestHeaders());
    String shipmentUrl = String.valueOf(buildShipmentUrl(message));
    try {
        typeRef = new ParameterizedTypeReference<Map<String, List<String>>>() {
        };
        log.info("Making REST call to the API >>");
        response = restTemplate.exchange(shipmentUrl, HttpMethod.GET, requestEntity, typeRef);
        if (response.getStatusCode().is2xxSuccessful()) {
            log.info("<<<<<<<<<<<<<<<<<<<<DATA RECEIVED>>>>>>>>>>>>>>>>>>>");
            log.info("Data recieved \n" + response.getBody());
        }
        log.info("<< Exiting callShipmentApi() after API call.");
    } catch (HttpClientErrorException ex) {
        if (ex.getStatusCode() == HttpStatus.SERVICE_UNAVAILABLE) {
            throw new AmqpRejectAndDontRequeueException(ex);
        }
    } catch (Exception e) {
        log.error("Internal server error occurred in API call. Bypassing message requeue {}", e);
        throw new AmqpRejectAndDontRequeueException(e);
    }

    return response.getBody();
}

0 个答案:

没有答案