当前位置: 首页 > 知识库问答 >
问题:

高负载测试spring webflux Webclient时出现的问题

岑毅庵
2023-03-14

我正在尝试学习来自C#和NetCore的Spring Webflow,我们有一个非常类似的问题,就像这篇文章一样,第三方服务提供商有一些响应时间问题。

但是使用spring-webClient进行测试会使响应时间加倍,我不知道我是否错过了什么

我尝试创建一个类似的示例:

  • 运行3台服务器的计算机

只是一条简单的路线

@Configuration
class TestRouter(private val middlemanDemo: MiddlemanDemo) {

    @Bean
    fun route() = router {
        GET("/testWait", middlemanDemo::middleTestAndGetWait)
    }
}

处理程序有一个带有种子的随机生成器,因此每个测试都可以生成相同的延迟序列

@Service
class TestWaiter {

    companion object RandomManager {

        private lateinit var random: Random

        init {
            resetTimer()
        }

        @Synchronized
        fun next(): Long {
            val random = random.nextLong(0, 10)
            return random * 2
        }

        fun resetTimer() {
            random = Random(12345)
        }
    }

    private val logger = LoggerFactory.getLogger(javaClass)

    fun testAndGetWait(request: ServerRequest): Mono<ServerResponse> {
        val wait = next()
        logger.debug("Wait is: {}", wait)
        return ServerResponse
                .ok()
                .json()
                .bodyValue(wait)
                .delayElement(Duration.ofSeconds(wait))
    }

    fun reset(request: ServerRequest): Mono<ServerResponse> {
        logger.info("Random reset")
        resetTimer()
        return ServerResponse
                .ok()
                .build()
    }
}

使用JMeter对服务器进行负载测试我可以看到大约9-10秒的稳定响应时间和100/s的最大吞吐量:

尝试使用C#的中间人,此服务器只是调用主演示服务器:

控制器

[HttpGet]
public async Task<string> Get()
{
    return await _waiterClient.GetWait();
}

以及httpClient的服务

    private readonly HttpClient _client;

    public WaiterClient(HttpClient client)
    {
        _client = client;
        client.BaseAddress = new Uri("http://192.168.0.121:8080");
    }

    public async Task<string> GetWait()
    {
        var response = await _client.GetAsync("/testWait");
        var waitTime = await response.Content.ReadAsStringAsync();
        return waitTime;
    }
}

测试此服务可以提供相同的响应时间,开销方面的吞吐量略低,但这是可以理解的

这个客户也很简单,就一条路

@Configuration
class TestRouter(private val middlemanDemo: MiddlemanDemo) {

    @Bean
    fun route() = router {
        GET("/testWait", middlemanDemo::middleTestAndGetWait)
    }
}

处理程序只是使用webclient调用服务

@Service
class MiddlemanDemo {

    private val client = WebClient.create("http://127.0.0.1:8080")

    fun middleTestAndGetWait(request: ServerRequest): Mono<ServerResponse> {
        return client
                .get()
                .uri("/testWait")
                .retrieve()
                .bodyToMono(Int::class.java)
                .flatMap(::processResponse)
    }

    fun processResponse(delay: Int): Mono<ServerResponse> {
        return ServerResponse
                .ok()
                .bodyValue(delay)
    }
}

但是,运行测试时,吞吐量仅达到50/秒

响应时间加倍,就像我再次等待,直到负载再次下降

共有2个答案

谭兴学
2023-03-14

我正在标记KL. Lee答案,因为它指出了我的正确方式,但我会添加完整的解决方案供任何人找到:

关键是根据我的需要创建一个连接池。正如JK. Lee所说,默认为500。

@Service
class MiddlemanDemo(webClientBuilder: WebClient.Builder) {

    private val client: WebClient

    init {
        val provider = ConnectionProvider.builder("fixed")
                .maxConnections(2000) // This is the important part
                .build()
        val httpClient = HttpClient
                .create(provider)
        client = webClientBuilder
                .clientConnector(ReactorClientHttpConnector(httpClient))
                .baseUrl("http://localhost:8080")
                .build()
    }

    fun middleTestAndGetWait(request: ServerRequest): Mono<ServerResponse> {

        return client
                .get()
                .uri("/testWait")
                .retrieve()
                .bodyToMono(Int::class.java)
                .flatMap(::processResponse)
    }

    fun processResponse(delay: Int): Mono<ServerResponse> {
        return ServerResponse
                .ok()
                .bodyValue(delay)
    }
}
贾沛
2023-03-14

我认为这可能是由于游泳池获得时间造成的。

我假设您的服务器有超过1k个TPS,每个请求看起来需要大约9秒钟。但是默认的HTTP客户端连接池是500。请参考投影仪反应器-连接池。

请检查日志PoolAcquireTimeoutException或者您的服务器是否需要一些时间来等待池获取。

 类似资料:
  • 问题内容: 我编写了使用文本协议接受连接和轰炸消息(〜100字节)的服务器,并且我的实现能够与3rt客户端发送约400K / sec的回送消息。我为此任务选择了Netty,即SUSE 11 RealTime,JRockit RTS。但是,当我开始基于Netty开发自己的客户端时,吞吐量却急剧下降(从400K msg / sec降低到1.3K msg / sec)。客户端的代码非常简单。能否请您提供

  • 嗨,由于我不知道负载测试,我在学习时有疑问。希望如果它是一个无效的也请让我帮助。 在jmeter中,我们可以简单地记录并正确地进行负载测试。如果是这样的话,如果我从我的客户端加载一些未知的应用程序,可能会导致服务器崩溃。然后,如果未知人员负载测试的服务器崩溃,他们该怎么办。 有没有什么具体的事情要做负载测试,或者只是我们可以在任何网站上做负载测试。请让我知道这件事,即使我的查询也不是有效的……提前

  • 我们目前对应用程序的负载测试是使用jMeter完成的,到目前为止运行良好。我们有三个不同的线程组,可以通过命令行标志分别启用和配置。还可以从命令行配置线程数和目标吞吐量。 我正在寻找的是为每个线程组编程负载场景的可能性。通常jMeter启动所有线程,然后尝试达到其目标吞吐量速率。我想要实现的如下:我配置目标吞吐量速率为每秒500个请求,启动速率为20,增量为20,持续时间为5分钟。jMeter应该

  • 主要内容:1. 项目依赖文件配置,2. @Test(invocationCount =?),3. @Test(invocationCount = ? threadPoolSize = ?),4. 负载测试示例在本教程中,我们将演示如何使用属性和在网站上执行负载测试或压力测试。 使用的工具 : TestNG 6.8.7 Selenium 2.39.0 Maven 3 我们使用库自动化浏览器来访问网站。创建一个用于测试的Maven项目:TestngSelenium 。 1. 项目依赖文件配置 获取T

  • 我的客户机正在使用EventHub的HTTPendpoint发布事件,这实际上意味着当客户机希望发布事件时,它会向一个特殊的URL发送HTTPS POST请求,例如: 我可以很容易地从本地机器上加载测试这个服务(例如,使用Apache JMeter),但不幸的是,本地机器的资源有限,所以我不能生成很大的负载来测试我的服务。 我说大负荷是什么意思? 如果没有,我如何加载测试我的基于EventHub的

  • 使用 Apache Ant 和 Apache JMeter 频繁进行负载测试 负载测试通常在开发周期的后期执行,但是并不一定要这样。在 让开发自动化的这一期,自动化专家 Paul Duvall 将向您描述如何创建一个运行 JMeter 测试的预订集成构建,发现和修复开发周期中出现的问题。 您的软件系统可供多少用户同时访问?在不引起性能下降的前提下可以加载多少数据?您的系统有多大的吞吐量需求?间隔多