查找WebSocket服务器内存泄漏

查找WebSocket服务器内存泄漏,websocket,.net-core,webserver,Websocket,.net Core,Webserver,大家好,我目前正在测试一个用Asp.Net Core 2.0编写的websocket服务器,我相信我有内存泄漏。我无法找到它,尽管我已经尝试处理了所有可能引起关注的问题。测试是连续进行的,ram的值在达到稳定状态时计算。(这从5秒到20秒不等)。 使用普通任务管理器监视器测量占用的Ram。测试工具:Thor: 命令:thor--amount[amount]ws://[HostIP(localhost)]:[portnumber] 结果: Connections | RAM Consumed at

大家好,我目前正在测试一个用Asp.Net Core 2.0编写的websocket服务器,我相信我有内存泄漏。我无法找到它,尽管我已经尝试处理了所有可能引起关注的问题。
测试是连续进行的,ram的值在达到稳定状态时计算。(这从5秒到20秒不等)。
使用普通任务管理器监视器测量占用的Ram。

测试工具
Thor

命令:
thor--amount[amount]ws://[HostIP(localhost)]:[portnumber]

结果

Connections | RAM Consumed at the end of test (GB):

0             4.54
50            4.55
100           4.55
150           4.61
200           4.68
300           4.76  
400           4.59
400           4.59
500           4.62
500           4.65
550           4.65
WebSocket服务器:

SocketMiddleware-由appbuilder使用:

public class SocketMiddleware
    {
        public  byte[] ToSegment(string message) => System.Text.Encoding.UTF8.GetBytes(message);
        ClientTracker clientTracker; //the socket clients tracker this is the object we're speaking of
        RequestDelegate next;
        public SocketMiddleware(ClientTracker tracker,RequestDelegate del)
        {
            this.clientTracker=tracker;
            this.next=del;   
        }
        public async Task Invoke(HttpContext context)
        {
            if(!context.WebSockets.IsWebSocketRequest)
            {
                await this.next.Invoke(context);
                return;
            }
            await this.clientTracker.AddClient(context.WebSockets);

        }
    }
SocketTracker-这是处理所有打开的插座的嫌疑人

  public class ClientTracker
        {
            ConcurrentDictionary<string, Client> clientMap = new ConcurrentDictionary<string, Client>();

            public string CreateConnectionID() => Guid.NewGuid().ToString();
            public string GetIDOfSocket(WebSocket socket) => this.clientMap.First(x => x.Value.webSocket.Equals(socket)).Key;
            public Client GetClientByID(string id)
            {
                this.clientMap.TryGetValue(id, out Client client);
                return client;
            }
            public async Task AddClient(WebSocketManager manager)
            {
               using (WebSocket socket = await manager.AcceptWebSocketAsync())
               {
                 Client newClient = Client.CreateClient(socket, CreateConnectionID());
                 if(clientMap.TryAdd(newClient.clientID, newClient))
                 {
                   await ReceiveMessage(newClient);
                 }

                }
             }

            public async Task ReceiveMessage(Client client)
            {
                while (client.webSocket.State == WebSocketState.Open)
                {
                    WebSocketReceiveResult result = await client.ReceiveResult();
                    //dosomething with result...
                    if (result.MessageType == WebSocketMessageType.Close)
                    {
                        await client.webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Client closed", CancellationToken.None);
                        break;
                    }
                    //send custom message 
                    await client.SendMessage("lala");
                }
            }
        }
公共类ClientTracker
{
ConcurrentDictionary clientMap=新建ConcurrentDictionary();
公共字符串CreateConnectionID()=>Guid.NewGuid().ToString();
公共字符串GetIDOfSocket(WebSocket套接字)=>this.clientMap.First(x=>x.Value.WebSocket.Equals(socket)).Key;
公共客户端GetClientByID(字符串id)
{
this.clientMap.TryGetValue(id,out-Client);
返回客户;
}
公共异步任务AddClient(WebSocketManager)
{
使用(WebSocket套接字=等待管理器.AcceptWebSocketAsync())
{
Client newClient=Client.CreateClient(socket,CreateConnectionID());
if(clientMap.TryAdd(newClient.clientID,newClient))
{
等待接收消息(新客户端);
}
}
}
公共异步任务接收消息(客户端)
{
while(client.webSocket.State==WebSocketState.Open)
{
WebSocketReceiveResult结果=等待客户端。ReceiveResult();
//结果是。。。
if(result.MessageType==WebSocketMessageType.Close)
{
wait client.webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure,“客户端已关闭”,CancellationToken.None);
打破
}
//发送自定义消息
等待客户发送消息(“lala”);
}
}
}
客户端-SocketTrapper,对套接字执行所有必需的操作,并存储跟踪程序使用的临时数据

public class Client
    {
        //Fields
        public readonly WebSocket webSocket;
        public readonly string clientID;
        public StringBuilder tempData;
        //Auxiliary
        private const int BufferSize = 1024 * 4;

        public static Client CreateClient(WebSocket socket, string id)
        {
            Client client = new Client(socket, id);
            return client;
        }

        public Client(WebSocket socket, string id)
        {
            this.webSocket = socket;
            this.clientID = id;
            tempData = new StringBuilder();
        }
        public async Task<WebSocketReceiveResult> ReceiveResult()
        {
            tempData.Clear();
            ArraySegment<byte> segment = new ArraySegment<byte>(new byte[BufferSize]);
            WebSocketReceiveResult result = await this.webSocket.ReceiveAsync(segment, CancellationToken.None);
            tempData.Append(BitConverter.ToString(segment.Array));
            return result;
        }

        public async Task SendMessage(string message)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(message);
            await this.webSocket.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Text, true, CancellationToken.None);
        }

    }
公共类客户端
{
//田地
公共只读WebSocket WebSocket;
公共只读字符串clientID;
公共数据;
//辅助的
private const int BufferSize=1024*4;
公共静态客户端CreateClient(WebSocket套接字,字符串id)
{
客户端=新客户端(套接字,id);
返回客户;
}
公共客户端(WebSocket套接字,字符串id)
{
this.webSocket=套接字;
this.clientID=id;
tempData=新的StringBuilder();
}
公共异步任务ReceiveResult()
{
tempData.Clear();
ArraySegment段=新的ArraySegment(新字节[BufferSize]);
WebSocketReceiveResult结果=等待this.webSocket.ReceiveAsync(段,CancellationToken.None);
Append(BitConverter.ToString(segment.Array));
返回结果;
}
公共异步任务SendMessage(字符串消息)
{
byte[]bytes=Encoding.UTF8.GetBytes(消息);
等待这个.webSocket.SendAsync(新的ArraySegment(字节),WebSocketMessageType.Text,true,CancellationToken.None);
}
}
Startup.cs

public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddSingleton<ClientTracker>();
        }
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseWebSockets();
            app.UseMiddleware<SocketMiddleware>();
        }
public void配置服务(IServiceCollection服务)
{
services.AddMvc();
services.AddSingleton();
}
公共无效配置(IApplicationBuilder应用程序,IHostingEnvironment环境)
{
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseWebSockets();
app.UseMiddleware();
}
附言:
请求之间未关闭服务器。可能是并发字典吗?除此之外,客户端的引用已清理,客户端已释放,套接字已关闭。无法释放字符串生成器,追踪器/中间件的寿命与应用程序的寿命一样长。

今天,我面临着同样的问题,显然没有解决方案。我有4万个独家产品,内存为1GB。当我关闭更新时,内存保持高位