TIdHTTPServer上下文计数不断增加

时间:2015-07-08 14:15:02

标签: delphi http indy

我创建了一个在Windows上运行的基于 TIdHTTPServer 的Web服务器。 Indy版本是最近的(2015年1月)。我将 MaxConnections 设置为1000,并且在调用 DoMaxConnections 时开发了一种重新启动Web服务器的机制。

每小时一次我记录连接数:

TIdThreadSafeList(IdHTTPServer1.Contexts).count;

在大多数情况下,连接数总是在增加。偶尔我会看到它减少(例如从525到520)。但整体趋势正在增加。大约5天后,它达到1000并且服务器重置(我知道1000相对较小,但不认为它与主题密切相关)。

即使在周末,当流量较低时,它仍会增加。我原本以为它会在流量较低时减少。为什么有些连接没有关闭?

netstat -an 并看到很多 TIME_WAIT 状态。

其他相关的源代码:

ServerIOHandler := TIdServerIOHandlerSSLOpenSSL.Create(self);
ServerIOHandler.SSLOptions.CertFile := 'C:\xxxxxx.crt';
ServerIOHandler.SSLOptions.KeyFile := 'C:\xxxxxx.key';
ServerIOHandler.SSLOptions.RootCertFile := 'C:=xxxxxx.crt';
ServerIOHandler.SSLOptions.Method := sslvSSLv23;
ServerIOHandler.SSLOptions.Mode := sslmServer;


IdHTTPServer1 := TIdHTTPServer.Create;
IdHTTPServer1.MaxConnections := 1000;
IdHTTPServer1.AutoStartSession := True;
IdHTTPServer1.KeepAlive := True;
IdHTTPServer1.SessionState := True;
IdHTTPServer1.OnCommandGet := MainGet;
idHttpServer1.ParseParams := True;

idHttpServer1.IOHandler := ServerIOHandler;
idHttpServer1.Bindings.Add.Port := 80;
idHttpServer1.Bindings.Add.Port := 443;
IdHTTPServer1.Active := True;

更新我认为添加一些netstat统计信息会很有用。

服务器运行24小时以上:

Contexts Count: 587
netstat ESTABLISHED from external to port 80:580
netstat TIME_WAIT   from external to port 80:819

然后我重新启动了我的Indy服务(但是没有重启Windows服务器):

Contexts Count: 60
netstat ESTABLISHED from external to port 80:49
netstat TIME_WAIT   from external to port 80:797

更新2 - 要求显示 MainGet 程序。可行的代码太多了。但我所做的是提供可以解决问题的代码片段。下面列出了我正在进行的一些通话(在不同情况下提高性能)。

AResponseInfo.ContentText := filetostring('c:\.....');
AResponseInfo.ResponseNo
Aresponseinfo.RawHeaders.Add('Connection:close');
Aresponseinfo.CustomHeaders.Add('Keep-Alive: timeout=30');
Aresponseinfo.Connection:='keep-alive';
AResponseInfo.ContentStream := MemoryStream;
AResponseInfo.Redirect('xxxxx');
AResponseInfo.ServeFile(AContext,mFile);
AResponseinfo.CacheControl:='max-age=1209600';

更新3 - 提供有关 MainGet 功能的其他信息。我正在跟踪函数被调用的次数和它退出的次数。 iGlobalGetStart和iGlobalGetFinish的值总是非常接近(当然比活跃的上下文数量少)。

  procedure TMyWebUnit.MainGet(AContext: TIdContext;
    ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
  try
    InterlockedIncrement(iGlobalGetStart);
    .... all of my logic
  finally
    InterlockedIncrement(iGlobalGetFinish);
  end;

更新4 - 我已实施其他跟踪代码。我创建了自己的类,来自 TIdServerContext 。在其中我设置了它的创建日期/时间,并且还有一个名为DatetimeLastUsed的日期/时间成员,它将在 oncommandget 中更新。这是班级:

type
  TEAIdServerContext = class(TIdServerContext)
    DateTimelastUsed,DateTimeCreated: TDateTime;
    constructor Create(AConnection: TIdTCPConnection; AYarn: TIdYarn; AList: TIdContextThreadList = nil); override;
    destructor Destroy; override;
  end;

我将 IdHTTPServer1.ContextClass 设置为这个新类:     IdHTTPServer1.ContextClass:= TEAIdServerContext;

在我的 OnCommandGet 中,我要做的第一件事就是将 DateTimeLastUsed 的日期/时间设置为当前时间:

TEAIDServerContext(AContext).DateTimeLastUsed := Now;

我还有一个列出所有上下文的函数:

procedure SayContexts();
var
  i: Integer;
  mstring: String;
  mList: TList;
begin

  mList := IdHTTPServer1.Contexts.LockList;
  mstring := 'Contexts:'+inttostr(mlist.Count);
  with mList do try
    for i := 0 to count -1 do begin
      mString := mString +
        datetimetostr(TEAIDServerContext(mList[i]).datetimecreated)+'; last used:'+datetimetostr(TEAIDServerContext(mList[i]).datetimeLastUsed)
    end;
  end;
  IdHTTPServer1.Contexts.UnLockList;
  ....
end;

保持打开的连接永远不会进入 oncommandget 代码,因为它们的datetimelastused字段为null。这是正常的吗?

0 个答案:

没有答案