spring-boot - Spring Integration Framework - 动态注册流程缓慢

标签 spring-boot spring-integration

我们正在开发一个 Spring Boot (2.4.0) 应用程序,它使用 Spring Integration 框架 (5.4.1) 构建 SOAP 集成流并动态注册它们。随着注册流数量的增加,使用“FlowContext”注册“IntegrationFlow”所花费的时间呈指数增长。 以下是注册流程所用时间的快速快照:

5 流 – 500 毫秒 100 次流量 – 80 秒 300 个流 – 300 秒

我们看到前几个流大约需要 100 毫秒来注册,当它达到 300 时,每个流的注册时间最多需要 7 秒。这些流在本质上是相同的(它们只是记录一条信息消息并返回)。

如果您能帮助解决此问题,我们将不胜感激。

SoapFlowsAutoConfiguration.java(动态(手动)注册流的自动配置类)

 @Bean
  public UriEndpointMapping uriEndpointMapping(
      ServerProperties serverProps,
      WebServicesProperties webServiceProps,
      IntegrationFlowContext flowContext,
      FlowMetadataProvider flowMetadataProvider,
      @ErrorChannel(Usage.SOAP) Optional<MessageChannel> errorChannel,
      BeanFactory beanFactory) {

    UriEndpointMapping uriEndpointMapping = new UriEndpointMapping();
    uriEndpointMapping.setUsePath(true);

    Map<String, Object> endpointMap = new HashMap<>();
    flowMetadataProvider
        .flowMetadatas()
        .forEach(
            metadata -> {
              String contextPath = serverProps.getServlet().getContextPath();
              String soapPath = webServiceProps.getPath();
              String serviceId = metadata.id();
              String serviceVersion = metadata.version();

              String basePath = contextPath + soapPath;

              String endpointPath = String.join("/", basePath, serviceId, serviceVersion);

              SimpleWebServiceInboundGateway inboundGateway = new SimpleWebServiceInboundGateway();
              errorChannel.ifPresent(inboundGateway::setErrorChannel);
              endpointMap.put(endpointPath, inboundGateway);
              IntegrationFlowFactory flowFactory = beanFactory.getBean(metadata.flowFactoryClass());

              IntegrationFlow integrationFlow =
                  IntegrationFlows.from(inboundGateway).gateway(flowFactory.createFlow()).get();
              flowContext.registration(integrationFlow).register();
            });
    uriEndpointMapping.setEndpointMap(endpointMap);
    return uriEndpointMapping;
  }

SoapFlow.java(集成流)

  @Autowired private SoapFlowResolver soapFlowResolver;
  @Autowired private CoreFlow delegate;

  @Override
  public IntegrationFlow createFlow() {
    IntegrationFlow a =
        flow -> flow.gateway(soapFlowResolver.resolveSoapFlow(delegate.createFlow()));
    return a;
  }

SoapFlowResolver.java(所有集成流使用的公共(public)类,用于将请求委托(delegate)给负责业务逻辑实现的 Coreflow)

public IntegrationFlow resolveSoapFlow(
      IntegrationFlow coreFlow) {

    return flow -> {
      flow.gateway(coreFlow);
    };
  }

CoreFlow.java(处理业务逻辑的类)

  @Override
  public IntegrationFlow createFlow() {

    return flow -> flow.logAndReply("Reached CoreFlow");
  }

最佳答案

您装入的 bean 过多,如果之前未创建,则每个 bean 都会检查其余的。当您动态添加越来越多的流时,这就是您如何随着开始时间的增加而增加。

我看到的是对动态流用途的滥用。每次我们决定采用这种方式时,如果我们确实需要将整个流程作为一个新实例,我们需要三思而后行。同样:流不是 volatile 对象,它在应用程序上下文中注册了一堆 bean,这些 bean 将一直保留在那里,直到您删除它们。而且它们是单例,因此可以在应用程序的任何其他地方重复使用。

另一个问题是您没有考虑 Spring Integration MessageChannel 模式实现的最佳特性。你当然可以提前有一些共同的流程,并通过它们之间的 channel 将你的动态与那些联系起来。您可能只需要动态创建一个 SimpleWebServiceInboundGateway 并将其连接到目标逻辑的 channel ,这对于所有流都是相同的等等。

关于spring-boot - Spring Integration Framework - 动态注册流程缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66494866/

相关文章:

java - 自定义存储库基类 + QueryDslPredicateExecutor

spring - 为传递依赖禁用 Spring Boot AutoConfiguration

java - 以编程方式重启 Spring Boot 应用程序/刷新 Spring Context

java - Spring Integration——聚合分散的消息

java - 如何验证使用 Spring SFTP 下载的文件的校验和

java - 将 Kafka Streams 用作 Kafka Consumer 应用程序中的状态存储

java - 在 Spring Boot 中忽略未映射到对象中的 json POJO 字段

java - Spring 集成: downloading only new or updated files from FTP server?

spring - 使用 Redis 保证消息传递

java - Spring Integration SFTP channel 适配器未将消息发送到下游服务激活器进行第二次轮询