簡體   English   中英

為什么在負載測試期間請求會干擾另一個請求並降低性能?

[英]Why do requests interfere with one another requests and slow performance with Spring Integration during load testing?

我在做什么? 我正在使用TLSv1.2連接到遠程服務器並發送最多300 字節的數據並接收到同樣大小的響應。

預計交付什么? 在負載測試期間,我們預計將提供1000TPS 最多使用 50 個持久 TLS 連接


出了什么問題?

  1. 在負載測試期間,我們收到的最大 TPS 是 250TPS。
  2. 在負載測試期間,我們觀察到請求正在干擾,導致一個請求的響應進入另一個請求響應。

配置:

@EnableIntegration
@IntegrationComponentScan
@Configuration
public class TcpClientConfig implements ApplicationEventPublisherAware {

  private ApplicationEventPublisher applicationEventPublisher;
  private final ConnectionProperty connectionProperty;

  @Override
  public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
    this.applicationEventPublisher = applicationEventPublisher;
  }

  TcpClientConfig(ConnectionProperty connectionProperty) {
    this.connectionProperty = connectionProperty;
  }

  @Bean
  public AbstractClientConnectionFactory clientConnectionFactory() {
    TcpNioClientConnectionFactory tcpNioClientConnectionFactory =
        getTcpNioClientConnectionFactoryOf(
            connectionProperty.getPrimaryHSMServerIpAddress(),
            connectionProperty.getPrimaryHSMServerPort());

    final List<AbstractClientConnectionFactory> fallBackConnections = getFallBackConnections();
    fallBackConnections.add(tcpNioClientConnectionFactory);

    final FailoverClientConnectionFactory failoverClientConnectionFactory =
        new FailoverClientConnectionFactory(fallBackConnections);

    return new CachingClientConnectionFactory(
        failoverClientConnectionFactory, connectionProperty.getConnectionPoolSize());
  }

  @Bean
  DefaultTcpNioSSLConnectionSupport connectionSupport() {

    final DefaultTcpSSLContextSupport defaultTcpSSLContextSupport =
        new DefaultTcpSSLContextSupport(
            connectionProperty.getKeystorePath(),
            connectionProperty.getTrustStorePath(),
            connectionProperty.getKeystorePassword(),
            connectionProperty.getTruststorePassword());

    final String protocol = "TLSv1.2";
    defaultTcpSSLContextSupport.setProtocol(protocol);
    return new DefaultTcpNioSSLConnectionSupport(defaultTcpSSLContextSupport, false);
  }

  @Bean
  public MessageChannel outboundChannel() {
    return new DirectChannel();
  }



  @Bean
  @ServiceActivator(inputChannel = "outboundChannel")
  public MessageHandler outboundGateway(AbstractClientConnectionFactory clientConnectionFactory) {
    TcpOutboundGateway tcpOutboundGateway = new TcpOutboundGateway();
    tcpOutboundGateway.setConnectionFactory(clientConnectionFactory);
    return tcpOutboundGateway;
  }
  @ServiceActivator(inputChannel = "error-channel")
  public void handleError(ErrorMessage em)  {
    Throwable throwable = em.getPayload();
    if(ExceptionUtils.indexOfThrowable(throwable, IOException.class)!=-1){
      ExceptionHandler.throwHsmSystemTimeoutException();
    }
    throw new RuntimeException(throwable);
  }

  private List<AbstractClientConnectionFactory> getFallBackConnections() {
    final int size = connectionProperty.getAdditionalHSMServersConfig().size();
    List<AbstractClientConnectionFactory> collector = new ArrayList<>(size);
    for (final Map.Entry<String, Integer> server :
        connectionProperty.getAdditionalHSMServersConfig().entrySet()) {
      collector.add(getTcpNioClientConnectionFactoryOf(server.getKey(), server.getValue()));
    }
    return collector;
  }

  private TcpNioClientConnectionFactory getTcpNioClientConnectionFactoryOf(
      final String ipAddress, final int port) {
    TcpNioClientConnectionFactory tcpNioClientConnectionFactory =
        new TcpNioClientConnectionFactory(ipAddress, port);
    tcpNioClientConnectionFactory.setUsingDirectBuffers(true);
    tcpNioClientConnectionFactory.setDeserializer(new CustomDeserializer());
    tcpNioClientConnectionFactory.setApplicationEventPublisher(applicationEventPublisher);
    tcpNioClientConnectionFactory.setSoKeepAlive(true);
    tcpNioClientConnectionFactory.setConnectTimeout(connectionProperty.getConnectionTimeout());
    tcpNioClientConnectionFactory.setSoTcpNoDelay(true);
    tcpNioClientConnectionFactory.setTcpNioConnectionSupport(connectionSupport());
    return tcpNioClientConnectionFactory;
  }
}

解串器

@Component
class CustomDeserializer extends DefaultDeserializer {
  private static final int MAX_LENGTH = 80;

  @Override
  public Object deserialize(final InputStream inputStream) throws IOException {
    StringBuilder stringBuffer = new StringBuilder(MAX_LENGTH);

    int read = Integer.MIN_VALUE;
    for (int loop = 0; loop < 300 && read != ']'; loop++) {
      read = inputStream.read();
      stringBuffer.append((char) read);
    }
    String reply = stringBuffer.toString();

    return reply;
  }

網關:

@Component
@MessagingGateway(defaultRequestChannel = "outboundChannel",errorChannel ="error-channel" )
public interface TcpClientGateway {
    String send(String message);
}

附加信息:

  1. 我們的服務部署在具有 8 到 10 個 Pod 的 GKE 上。
  2. 目標服務器能夠處理超過 2000TPS,我們被許可僅使用 1000TPS。

查看連接工廠的singleUse選項:

/**
 * If true, sockets created by this factory will be used once.
 * @param singleUse The singleUse to set.
 */
public void setSingleUse(boolean singleUse) {

然后查看TcpOutboundGateway的 JavaDocs :

 * TCP outbound gateway that uses a client connection factory. If the factory is configured
 * for single-use connections, each request is sent on a new connection; if the factory does not use
 * single use connections, each request is blocked until the previous response is received
 * (or times out). Asynchronous requests/responses over the same connection are not
 * supported - use a pair of outbound/inbound adapters for that use case.

我不確定TPS是什么,但如果知道您的服務器端正在做什么以確保對請求的回復的相關性將正確發生,那就太好了。

暫無
暫無

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

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