【问题标题】:Spring application 300 TPS bottleneckSpring 应用 300 TPS 瓶颈
【发布时间】:2021-02-28 18:53:15
【问题描述】:

我有一个在 Spring 上运行的 Java 应用程序,它有一个创建发票的服务,每张发票有 10 次读写。但是我们无法让它通过 150TPS(每秒事务数),硬件没有达到 30% 的容量,我们将 maxpool 大小设置为 300,DB 设置为 3000 i/o,我们没有看到任何改进,我不确定它代码或配置

AWS DB Monitor

public class InvoiceHomeService {

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

    private final DosageService dosageService;

    private final DosageRepository dosageRepository;

    private final InvoiceService invoiceService;

    private final ApplicationProperties applicationProperties;

    public Invoice create(Company company,
                          CreateInvoiceHomeRequest request,
                          Branch branch,
                          EconomicActivity economicActivity,
                          String modalityId) throws DosageNotAvailableException, DateOutRangeException {

        Sorter invoiceType = new Sorter(SortersConstants.HOME);
        DosageTransaction dosageTransaction = getDosageTransaction(request, company, economicActivity, invoiceType, modalityId);

        Invoice invoice = new Invoice();

        /* Critital information */
        invoice.setExternalId(request.getId());
        invoice.setInvoiceType(invoiceType);
        invoice.setInvoiceMethod(new Sorter(SortersConstants.IM_VIRTUAL));
        invoice.setTotalAnticipatedPayment(BigDecimal.ZERO);

        /* Basic information */
        invoice.setContractId(request.getContractId());
//        invoice.setCustomerId(request.getCustomerId());
        invoice.setBillingPeriod(request.getBillingPeriod());
        invoice.setVoucherNumber(request.getVoucherNumber());
        invoice.setVoucherType(request.getVoucherType());
//        invoice.setVoucherSerial(request.getVoucherSerial());
        invoice.setVoucherState(request.getVoucherState());
        invoice.setPaymentType(request.getTypeOfPayment());
        invoice.setEmailNotification(request.getEmailNotification());
        invoice.setPhoneNumberNotification(request.getPhoneNumberNotification());
        invoice.setIsTigo(request.getIsTigo());
        invoice.setPersonType(request.getTypeOfPerson());

        /* Extras information */
//        invoice.setExtraPhoneLine(request.getExtraPhoneLine());
//        invoice.setExtraPlan(request.getExtraPlan());
        invoice.setExtraCustomerAddress(request.getExtraCustomerAddress());
        invoice.setExtraPeriodStartdate(request.getExtraPeriodStartdate());
        invoice.setExtraPeriodEnddate(request.getExtraPeriodEnddate());
        invoice.setExtraPaydayLimit(request.getExtraPaymentDeadline());
        invoice.setExtraServiceInterruptionDate(request.getExtraServiceInterruptionDate());
        invoice.setExtraPeriodDays(request.getExtraPeriodDays());

        /* Customer Information */
        invoice.setNitCustomer(request.getNitCustomer());
        invoice.setSocialReason(request.getSocialReason());

        /* Invoice template */
        invoice.setInvoiceTemplate(JasperSingleton.INVOICE_TEMPLATE_HOME_VERSION);

        Set<InvoiceDetails> details = new HashSet<>();
        for (CreateInvoiceDetailsHomeRequest detail : request.getDetails()) {
            InvoiceDetails item = new InvoiceDetails();
            item.setQuantity(detail.getQuantity());
            item.setConcept(detail.getConcept());
            item.setUnitPrice(detail.getUnitPrice());
            item.setSequence(detail.getSequence());
            item.setSubtotal(detail.getSubtotal());
            item.setExtraPeriod(detail.getExtraPeriod());
            details.add(item);
        }
        invoice.setDetails(details);

        invoice = invoiceService.createInvoice(
            invoice,
            dosageTransaction.getDosage(),
            company,
            branch,
            economicActivity,
            dosageTransaction.getSequence(),
            request.getEmissionDate(),
            request.getEmissionDate(),
            request.getTotalAmount(),
            economicActivity.getType()
        );

        return invoice;
    }

    public synchronized DosageTransaction getDosageTransaction(CreateInvoiceHomeRequest request, Company company, EconomicActivity economicActivity, Sorter invoiceType, String modalityId) throws DosageNotAvailableException, DateOutRangeException {
        Optional<Dosage> optionalDosage = dosageService.getDosageActive(company.getId(), invoiceType.getSequence(),
            economicActivity.getId(), SortersConstants.DT_CYCLE, modalityId, invoiceType.getId());
        if (!optionalDosage.isPresent()) throw new DosageNotAvailableException();
        Dosage dosage = optionalDosage.get();

        if (!request.getEmissionDate().isAfter(dosage.getStartDate().minusDays(1)) ||
            !request.getEmissionDate().isBefore(dosage.getDeadlineDate().plusDays(1))) throw new DateOutRangeException();

        if (modalityId.equalsIgnoreCase(SortersConstants.DM_CICLICAL) && dosage.getSequence() > applicationProperties.getDosageConfig().getMaxInvoicePerDosage().longValue()) {
            dosage.setState(new Sorter(SortersConstants.DS_LOCKED));
            dosage = dosageRepository.save(dosage);
            log.info("Change state dosage: {}, state: {}", dosage.getId(), dosage.getState().getId());
            return getDosageTransaction(request, company, economicActivity, invoiceType, modalityId);
        }

        Long sequence = invoiceService.getSequenceDosageSync(dosage.getId());
        return new DosageTransaction(dosage, sequence);
    }
}

【问题讨论】:

  • 那么为什么你认为你需要 300 TPS?您是否正在尝试满足某些特定的软件要求?目标不一定是使 CPU 利用率饱和;可能还有其他限制因素。建立另一个 AWS 实例不是更容易吗?
  • 是的,我们需要满足每秒 300 个事务来处理负载,集群不是一个选项。
  • 使用序列会影响性能,因为它需要为每个事务锁定序列表。它是一个缓存序列还是可能在插入语句中调用nextval
  • 那么,您可以使用哪些分析工具?在任何其他普通应用程序中,我要做的第一件事就是测量。
  • 为什么要同步getDosageTransaction?如果没有,会发生什么?您是否测量了您的网络活动以及往返需要多长时间?事务边界是什么?

标签: java performance spring-data database-concurrency


【解决方案1】:

后来我们发现用JAVA生成序列就是制造瓶颈。

使用“nexval”让 postgresql 创建序列将我们的性能提高到 800TPS

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-18
    • 2011-04-02
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多