服务器开发
总结了一些经验,现贴出于大家讨论。   
1、构件的使用    
   开始我一直使用Indy,但最近在开发一个100-350并发用户的服务器端时发现了Indy问题,由于用户的访问非常繁重,服务器工作两周后出现了70多的废连接。导致服务器响应变的慢。而且我观察到有时INDY能自动释放这些废连接,有时多到200多都不释放。后来我改DXSock 3.0构件,代码没有作任何改动,服务从6月1日到今天没有重启一次而且没有一个废连接,    
   我花了一周看DXSock的代码,改了些错误,也学习了很多,DXSock构成思想很好。它的连接响应线程不是动态创建的,而是你设置多少就一次性创建多少。节省了创建、释放的大量时间。    
   所以再开发服务器端软件我推进使用DXSOCK构件。    
   2、数据库使用    
      很多朋友在讨论多线程中使用数据库的问题,这在网络服务器开发中这是常常需要考虑的问题,很多朋友都采用一个线程建立一个数据库的连接,我认为这种方法在小规模、小并发应用中是可以的,但是一旦负荷上去、并发一多这样就很多问题了,比如资源消耗(数据库)、时间消耗。这种方式我用过,结果是运行一段时间后数据库再也连接不上了。    
      我再这方面有两个解决办法:    
      a、采用ASTA构件的方法,根据分析负荷一次性创建一个ADOCONNEC连接池,靠一个同步模块来管理,客户端请求-》构造SQL-》让同步管理模块来分配一个ADOCONNECT联机-》执行SQL,返回结果,如果这时ADOCONNECT满,此SQL等待。代码如下:    
      b、对于不需要实时返回数据库信息的应用,客户端请求来-》服务器创建SQL语句和一个TAG-》SQL语句送入队列,然后一条一条的执行,TAG返回客户端,过一段时间客户端再通过这个TAG来服务端获得结果。    
********************************************队列管理代码***********************    
Unit uitQueueManage;    
Interface    
Uses    
  Windows,    
  Messages,    
  SysUtils,    
  Variants,    
  Classes,    
  Contnrs;    
Type    
  TSyncManage = Class(TObject)    
  Protected    
    FHandle: THandle;    
  Public    
    Property Handle: THandle Read FHandle;    
    Constructor Create(Const Name: String; InitCount, MaxBuffer: Integer);    
    Destructor Destroy; Override;    
    Function Release: Boolean; Overload;    
    Function WaitFor(TimeOut: Integer): Boolean;    
  End;    
Type    
  PQueueItem = ^TQueueItem;    
  TQueueItem = Record    
    FRequestCount: Integer;    
    FCommand: Integer;    
    FDataStr: String;    
    FDataInt: Integer;    
    FDataBool: Boolean;    
  End;    
  TProgressEvent = Procedure(Sender: TObject; aQueueItem: TQueueItem) Of Object;    
  TQueueManage = Class(TObject)    
  Private    
    FQueue: TQueue;    
    FSyncManage: TSyncManage;    
    FOnProgress: TProgressEvent;    
    FLock: TRTLCriticalSection;    
  Public    
    Constructor Create(aQueueName: String; aBuffer: Integer);    
    Destructor Destroy; Override;    
    Procedure PushQueue(aQueueItem: TQueueItem);    
  Published    
    Property OnProgress: TProgressEvent Read FOnProgress Write FOnProgress;    
  End;    
Type    
  TQueueThread = Class(TThread)    
  Private    
    hSyncManage: TSyncManage;    
    hOwner: TQueueManage;    
    hQueue: TQueue;    
    Procedure DoProgress;    
  Protected    
    Procedure Execute; Override;    
  Public    
    Constructor Create(aOwner: TQueueManage; aQueue: TQueue; aSyncManage: TSyncManage); Virtual;    
  End;    
Implementation    
//***********************************************************TSyncThread**************************    
Constructor TSyncManage.Create(Const Name: String; InitCount, MaxBuffer: Integer);    
Begin    
  FHandle := CreateSemaphore(Nil, InitCount, MaxBuffer, Pchar(Name));    
  If FHandle = 0 Then abort;    
End;    
Destructor TSyncManage.Destroy;    
Begin    
  If FHandle <> 0 Then CloseHandle(FHandle);    
End;    
Function TSyncManage.WaitFor(TimeOut: Integer): Boolean;    
Begin    
  Result := WaitForSingleObject(FHandle, TimeOut) = WAIT_OBJECT_0;    
End;    
Function TSyncManage.Release: Boolean;    
Begin    
  Result := ReleaseSemaphore(FHandle, 1, Nil);    
End;    
//***********************************************************TQueueThread**************************    
Constructor TQueueThread.Create(aOwner: TQueueManage; aQueue: TQueue; aSyncManage: TSyncManage);    
Begin    
  Inherited Create(True);    
  hOwner := aOwner;    
  hQueue := aQueue;    
  hSyncManage := aSyncManage;    
  Priority := tpHigher;    
  Resume;    
End;    
Procedure TQueueThread.Execute;    
Begin    
  While Not Terminated Do    
  Begin    
    hSyncManage.WaitFor(Integer(INFINITE)); //无限等    
    If Terminated Then Exit;    
    DoProgress;    
  End;    
End;    
Procedure TQueueThread.DoProgress;    
Var    
  mQueueItem: PQueueItem;    
Begin    
  mQueueItem := hQueue.Pop;    
  If Assigned(hOwner.FOnProgress) Then hOwner.FOnProgress(hOwner, mQueueItem^);    
  Dispose(mQueueItem);    
End;    
//***********************************************************TQueueManage*************************    
Var    
  FQueueThread: TQueueThread;    
Constructor TQueueManage.Create(aQueueName: String; aBuffer: Integer);    
Begin    
  Inherited Create;    
  InitializeCriticalSection(FLock);    
  FQueue := TObjectQueue.Create;    
  FSyncManage := TSyncManage.Create(aQueueName, 0, aBuffer); //缓冲区大小    
  FQueueThread := TQueueThread.Create(Self, FQueue, FSyncManage);    
End;    
Destructor TQueueManage.Destroy;    
Begin    
  EnterCriticalSection(FLock);    
  Try    
    FQueueThread.Terminate;    
    FSyncManage.Release;    
    FreeAndNil(FQueueThread);    
    FreeAndNil(FSyncManage);    
    FreeAndNil(FQueue);    
    Inherited Destroy;    
  Finally    
    LeaveCriticalSection(FLock);    
    DeleteCriticalSection(FLock);    
  End;    
End;    
Procedure TQueueManage.PushQueue(aQueueItem: TQueueItem);    
Var    
  mQueueItem: PQueueItem;    
Begin    
  New(mQueueItem);    
  mQueueItem^ := aQueueItem;    
  EnterCriticalSection(FLock);    
  FQueue.Push(mQueueItem);    
  LeaveCriticalSection(FLock);    
  FSyncManage.Release;    
End;    
End.    
********************************************队列管理代码***********************    
ADO连接同步管理我稍后放上来,欢迎大家讨论。  
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号