簡體   English   中英

如何並行執行Hystrix命令?

[英]How to execute Hystrix commands in parallel?

我的應用程序中的一種Spring服務方法向其他兩個微服務發出請求。 我想使用Hystrix發出這些請求以使其具有容錯能力,我想並行運行它們。

到目前為止,我為每個調用實現了HystrixObservableCommand,並使用CountDownLatch等待兩個命令完成(或失敗)。

當前的解決方案看起來很冗長。 是否可以使用可觀察功能並行執行Hystrix命令?

所需的解決方案看起來像是偽代碼:

new LoadCustomerObservableCommand(customerClient, customerId).toObservable()
    .doOnError(throwable -> log.error("Failed to retrieve customer {} information for the reservation {}", customerId, reservationId, throwable))
    .doOnNext(customer -> myResponse.setCustomer(customer));

new GetTicketsObservableCommand(ticketsClient, reservationId).toObservable()
    .doOnError(throwable -> log.error("Failed to retrieve tickets for the reservation {}", reservationId, throwable))
    .doOnNext(tickets -> myResponse.setTickets(tickets));

final AtomicBoolean subRequestsFailed = new AtomicBoolean(false);

Observable.zip(customerObservable, ticketsObservable, (customer, tickets) -> null)
    .doOnError(throwable -> subRequestsFailed.set(true))
    .toBlocking()
    .first();

if (subRequestsFailed.get()) {
     throw new HystrixBadRequestException("One or more requests to submodules have been failed");
}

return dto;

不幸的是,此理想的解決方案無法正常工作,因為從不執行Hystrix命令。

我當前的解決方案是:

    // execute requests to sub modules in parallel
    final CountDownLatch cdl = new CountDownLatch(2);
    final List<Throwable> failures = new ArrayList<>();

    // load customer information
    final Observable<CustomerDTO> customerObservable = customerRxClient.loadCustomer(customerId);

    customerObservable
            .doOnError(throwable -> {
                log.error("Failed to retrieve customer {} information for the reservation {}", customerId, reservationId, throwable);

                cdl.countDown();

                failures.add(throwable);
            })
            .doOnCompleted(cdl::countDown)
            .subscribe(customer -> {
                dto.getReservationOwner().setBirthday(customer.getBirthday());
                dto.getReservationOwner().setCustomerId(customer.getCustomerId());
                dto.getReservationOwner().setCitizenship(customer.getCitizenship());
                dto.getReservationOwner().setEmail(customer.getEmail());
                dto.getReservationOwner().setFirstName(customer.getFirstName());
                dto.getReservationOwner().setGender(customer.getGender());
                dto.getReservationOwner().setLastName(customer.getLastName());
                dto.getReservationOwner().setPhone(ofNullable(customer.getPhone()).map(v -> mappingService.map(v, PhoneDTO.class)).orElse(null));
            });

    // load tickets
    final Observable<List<TicketDTO>> ticketsObservable = ticketsClient.getTickets(reservationId);

    ticketsObservable
            .doOnError(throwable -> {
                log.error("Failed to retrieve tickets for the reservation {}", reservationId, throwable);

                cdl.countDown();

                failures.add(throwable);
            })
            .doOnCompleted(cdl::countDown)
            .subscribe(tickets -> dto.setTickets(tickets.stream()
                    .map(ticket -> ReservationDTO.TicketDTO.builder()
                            .guestSeqN(ticket.getGuestSeqN())
                            .qr(ticket.getQr())
                            .qrText(ticket.getQrText())
                            .usedAt(ticket.getUsedAt())
                            .build())
                    .collect(toList())));

    try {
        cdl.await();
    } catch (InterruptedException _ignore) {
        log.debug("Count down latch has been interrupted!", _ignore);
    }

    if (!failures.isEmpty()) {
        throw new HystrixBadRequestException("Request to submodule has been failed");
    }

 return dto;

您希望使用正確的解決方案,因為它使用了zip組合器。 在該解決方案中未執行Hystrix命令的原因是,生成的Observable沒有訂閱者。 文檔中

toObservable() —返回一個“冷”的Observable,在您訂閱結果Observable之前,該Observable不會訂閱基礎的Observable

只需在組合的Observable上調用subscribe()方法:

Observable.zip(customerObservable, ticketsObservable, (customer, tickets) -> null)
          .take(1)
          .doOnError(throwable -> subRequestsFailed.set(true))
          .subscribe();

經過一番挖掘,我找到了解決方案。 我的代碼中錯過的操作是“ subscribeOn”:

ResponseDTO result = Observable.zip(
            saleChannelPaxInventoryClient.getAvailabilities(saleChannel, routeLeg, date).subscribeOn(Schedulers.io()),
            saleChannelCarDeckInventoryClient.getAvailabilities(saleChannel, routeLeg, date).subscribeOn(Schedulers.io()),
            (paxAvailabilities, carDeckAvailabilities) -> {
               ResponseDTO out = new ResponseDTO();
               // process results of both observables here

               return out;
            }
    )
.toBlocking()
.single();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM