相关疑难解决方法(0)

基于TcpListener的应用程序,不能很好地扩展

我有一个基于a的ECHO服务器应用程序TCPListener.它接受客户端,读取数据并返回相同的数据.我使用async/await方法开发了它,使用XXXAsync框架提供的方法.

我设置了性能计数器来测量输入和输出的消息和字节数,以及连接的插槽数.

我创建了一个启动1400异步的测试应用程序TCPClient,并且每100-500ms发送一条1Kb消息.客户端在开始时有10-1000毫秒的随机等待启动,因此他们不会尝试同时连接所有客户端.我运作良好,我可以在PerfMonitor中看到1400连接,以良好的速率发送消息.我从另一台计算机上运行客户端应用程序 服务器的CPU和内存使用率非常低,它是带有8Gb RAM的Intel Core i7.客户端看起来比较忙,它是带有4Gb内存的i5,但仍然不是25%.

问题是如果我启动另一个客户端应用程序.连接在客户端中开始失败.我没有看到每秒消息的大幅增加(或多或少增加20%),但我看到连接客户端的数量大约是1900-2100,而不是预期的2800.性能略有下降,图表显示每秒最大和最小消息之间的差异比以前更大.

尽管如此,CPU使用率仍然不是40%,内存使用量仍然很少.我试图在客户端和服务器中增加数量或池线程:

ThreadPool.SetMaxThreads(5000, 5000);
ThreadPool.SetMinThreads(2000, 2000);
Run Code Online (Sandbox Code Playgroud)

在服务器中,循环接受连接:

while(true)
{
    var client = await _server.AcceptTcpClientAsync();
    HandleClientAsync(client);
}
Run Code Online (Sandbox Code Playgroud)

HandleClientAsync函数返回a Task,但正如您所看到的循环不等待处理,只是继续接受另一个客户端.处理函数是这样的:

public async Task HandleClientAsync(TcpClient client)
{    
    while(ws.Connected && !_cancellation.IsCancellationRequested)
    {
        var msg = await ReadMessageAsync(client);
        await WriteMessageAsync(client, msg);
    }
}
Run Code Online (Sandbox Code Playgroud)

这两个函数只是异步读写流.

我看到我可以开始TCPListener指示backlog金额,但默认值是多少?

为什么可能是应用程序在达到最大CPU之前没有扩展的原因?

找出实际问题的方法和工具是什么?

UPDATE

我曾尝试Task.YieldTask.Run办法,他们没有帮助.

服务器和客户端也在同一台计算机上本地运行.每秒增加客户端或消息量实际上会降低服务吞吐量.600个客户端每100ms发送一条消息,产生的吞吐量超过1000个客户端每100ms发送一条消息.

当连接超过~2000个客户端时,我在客户端看到的例外是两个.大约1500年我开始看到例外,但客户最终连接.超过1500我看到很多连接/断开:

"远程主机强行关闭现有连接"(System.Net.Sockets.SocketException)捕获到System.Net.Sockets.SocketException:"远程主机强行关闭现有连接"

"无法将数据写入传输连接:远程主机强制关闭现有连接." (System.IO.IOException)抛出System.IO.IOException:"无法将数据写入传输连接:远程主机强制关闭现有连接."

更新2

我已经使用async/await建立了一个非常简单的服务器和客户端项目,并按预期进行扩展.

我有可扩展性问题的项目就是 …

.net multithreading asynchronous tcplistener async-await

5
推荐指数
1
解决办法
1465
查看次数