Multithreading Tomcat上的SpringWeb服务端点-并发调用配置
我有一个Spring应用程序,它有一个Web服务Multithreading Tomcat上的SpringWeb服务端点-并发调用配置,multithreading,spring-mvc,tomcat7,spring-integration,Multithreading,Spring Mvc,Tomcat7,Spring Integration,我有一个Spring应用程序,它有一个Web服务端点,在收到一个调用时,它会将请求负载传递给Spring IntegrationMessagingGateway,以进行EIP处理 我的应用程序部署在一个tomcat7容器上,并使用spring4api构建 我正在尝试运行一个性能测试,在该测试中,我对web服务进行多个并发调用。当我执行这个测试时,每个请求都得到了很好的处理,并且成功地收到了每个请求的响应,但是Spring应用程序似乎在处理两个请求。i、 e.第三个请求仅在第二个请求的响应发送回客
端点
,在收到一个调用时,它会将请求负载传递给Spring IntegrationMessagingGateway
,以进行EIP处理
我的应用程序部署在一个tomcat7
容器上,并使用spring4api构建
我正在尝试运行一个性能测试,在该测试中,我对web服务进行多个并发调用。当我执行这个测试时,每个请求都得到了很好的处理,并且成功地收到了每个请求的响应,但是Spring应用程序似乎在处理两个请求。i、 e.第三个请求仅在第二个请求的响应发送回客户端后由应用程序处理。(调试时,我可以看到只有两个线程处理请求)
我想知道我的Spring应用程序的执行线程配置应该在哪里进行,以便支持并发处理多个web服务客户端请求(例如,10个以上并发线程)。这应该在Tomcat容器的配置中的某个地方完成吗?Web服务配置中的某个地方?Spring集成的消息网关配置?Spring集成的请求集成流配置?这些配置的组合?或者完全在别的地方
我的堆栈是:
Tomcat 7.0.55
Spring/Integration 4 APIs
Spring Java DSL 1 API
对于我的测试,我使用的是SoapUI 4.5.0,我正在使用以下配置执行负载测试:
@Endpoint
@EnableIntegration
@IntegrationComponentScan(basePackages = "com.company.test.gateway")
@ComponentScan(basePackages = "com.company.test.gateway")
public class TestServiceEndpoint {
private static final String NAMESPACE_URI = "http://www.company.com/test";
private static final Logger logger = LogManager.getLogger();
@Autowired
private TestGateway gateway;
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "test")
@ResponsePayload
public TestResponse process(
@RequestPayload TestRequest request) throws Exception {
TestResponse response = gateway.process(request);
return response;
}
}
@MessagingGateway
@EnableIntegration
@IntegrationComponentScan
@ComponentScan
public interface TestGateway {
@Gateway(requestChannel = "test.request.ch", replyChannel = "test.response.ch")
TestResponse process(TestRequest request);
}
@Configuration
public class IntegrationConfig {
@Bean(name = "test.request.ch")
public DirectChannel testRequestCh() {
return new DirectChannel();
}
@Bean(name = "test.response.ch")
public DirectChannel testResponseCh() {
return new DirectChannel();
}
@Bean
public Executor taskExecutor() {
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors
.newFixedThreadPool(10);
return executor;
}
@Bean
public IntegrationFlow requestFlow() {
return IntegrationFlows
.from("test.request.ch")
.enrichHeaders(
m -> {
m.header(MessageHeaders.ERROR_CHANNEL,
"test.error.ch", true);
})
.handle("testSplitter", "split")
.channel(MessageChannels.executor("requestSplitterFlowExecutor",
this.taskExecutor()))
.route("testRouter", "route")
.get();
}
...
}
线程:10,策略:线程,开始线程:10,结束线程:10,每个线程限制运行1次。
我假设这个配置可以测试对web服务URL的10个并发调用
*更新以包括当前配置*
端点配置:
@Endpoint
@EnableIntegration
@IntegrationComponentScan(basePackages = "com.company.test.gateway")
@ComponentScan(basePackages = "com.company.test.gateway")
public class TestServiceEndpoint {
private static final String NAMESPACE_URI = "http://www.company.com/test";
private static final Logger logger = LogManager.getLogger();
@Autowired
private TestGateway gateway;
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "test")
@ResponsePayload
public TestResponse process(
@RequestPayload TestRequest request) throws Exception {
TestResponse response = gateway.process(request);
return response;
}
}
@MessagingGateway
@EnableIntegration
@IntegrationComponentScan
@ComponentScan
public interface TestGateway {
@Gateway(requestChannel = "test.request.ch", replyChannel = "test.response.ch")
TestResponse process(TestRequest request);
}
@Configuration
public class IntegrationConfig {
@Bean(name = "test.request.ch")
public DirectChannel testRequestCh() {
return new DirectChannel();
}
@Bean(name = "test.response.ch")
public DirectChannel testResponseCh() {
return new DirectChannel();
}
@Bean
public Executor taskExecutor() {
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors
.newFixedThreadPool(10);
return executor;
}
@Bean
public IntegrationFlow requestFlow() {
return IntegrationFlows
.from("test.request.ch")
.enrichHeaders(
m -> {
m.header(MessageHeaders.ERROR_CHANNEL,
"test.error.ch", true);
})
.handle("testSplitter", "split")
.channel(MessageChannels.executor("requestSplitterFlowExecutor",
this.taskExecutor()))
.route("testRouter", "route")
.get();
}
...
}
网关配置:
@Endpoint
@EnableIntegration
@IntegrationComponentScan(basePackages = "com.company.test.gateway")
@ComponentScan(basePackages = "com.company.test.gateway")
public class TestServiceEndpoint {
private static final String NAMESPACE_URI = "http://www.company.com/test";
private static final Logger logger = LogManager.getLogger();
@Autowired
private TestGateway gateway;
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "test")
@ResponsePayload
public TestResponse process(
@RequestPayload TestRequest request) throws Exception {
TestResponse response = gateway.process(request);
return response;
}
}
@MessagingGateway
@EnableIntegration
@IntegrationComponentScan
@ComponentScan
public interface TestGateway {
@Gateway(requestChannel = "test.request.ch", replyChannel = "test.response.ch")
TestResponse process(TestRequest request);
}
@Configuration
public class IntegrationConfig {
@Bean(name = "test.request.ch")
public DirectChannel testRequestCh() {
return new DirectChannel();
}
@Bean(name = "test.response.ch")
public DirectChannel testResponseCh() {
return new DirectChannel();
}
@Bean
public Executor taskExecutor() {
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors
.newFixedThreadPool(10);
return executor;
}
@Bean
public IntegrationFlow requestFlow() {
return IntegrationFlows
.from("test.request.ch")
.enrichHeaders(
m -> {
m.header(MessageHeaders.ERROR_CHANNEL,
"test.error.ch", true);
})
.handle("testSplitter", "split")
.channel(MessageChannels.executor("requestSplitterFlowExecutor",
this.taskExecutor()))
.route("testRouter", "route")
.get();
}
...
}
集成配置:
@Endpoint
@EnableIntegration
@IntegrationComponentScan(basePackages = "com.company.test.gateway")
@ComponentScan(basePackages = "com.company.test.gateway")
public class TestServiceEndpoint {
private static final String NAMESPACE_URI = "http://www.company.com/test";
private static final Logger logger = LogManager.getLogger();
@Autowired
private TestGateway gateway;
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "test")
@ResponsePayload
public TestResponse process(
@RequestPayload TestRequest request) throws Exception {
TestResponse response = gateway.process(request);
return response;
}
}
@MessagingGateway
@EnableIntegration
@IntegrationComponentScan
@ComponentScan
public interface TestGateway {
@Gateway(requestChannel = "test.request.ch", replyChannel = "test.response.ch")
TestResponse process(TestRequest request);
}
@Configuration
public class IntegrationConfig {
@Bean(name = "test.request.ch")
public DirectChannel testRequestCh() {
return new DirectChannel();
}
@Bean(name = "test.response.ch")
public DirectChannel testResponseCh() {
return new DirectChannel();
}
@Bean
public Executor taskExecutor() {
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors
.newFixedThreadPool(10);
return executor;
}
@Bean
public IntegrationFlow requestFlow() {
return IntegrationFlows
.from("test.request.ch")
.enrichHeaders(
m -> {
m.header(MessageHeaders.ERROR_CHANNEL,
"test.error.ch", true);
})
.handle("testSplitter", "split")
.channel(MessageChannels.executor("requestSplitterFlowExecutor",
this.taskExecutor()))
.route("testRouter", "route")
.get();
}
...
}
干杯,
PM应用程序一次只处理两条消息(有时甚至只处理一条ata!)的原因根本不是因为Spring配置或Tomcat配置中存在问题,而是因为测试工具SoapUI 4.5.0中存在错误。看
更新SoapUI并重新运行后,现在可以看到消息一次由多个线程处理。您需要显示集成配置。如果始终使用
DirectChannel
s,则集成流将在tomcat http线程上运行,该线程不应限于2个。嗨,与网关直接关联的通道是DirectChannel
s。然而,随着流程的进一步深入,事情会变得更加复杂,这取决于消息的路由方式。在我当前运行的性能测试中,testRouter
将有效负载路由到PublishSubscribeChannel
,其中有效负载放置在MQ队列中。这是一个发布子频道的原因是,一旦我们知道有效负载已成功放入队列,我们就会进行其他工作。此后,响应最终通过JMS入站适配器到达,并发送到test.response.ch
返回网关。框架中没有任何限制线程的内容。我建议您打开调试日志并遵循消息流;确保包含线程名称(%t
如果是log4j),以便查看发生了什么。