• 服务器开发


    总结了一些经验,现贴出于大家讨论。
    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连接同步管理我稍后放上来,欢迎大家讨论。 

  • 相关阅读:
    图解攻略:轻松在苹果Macbook Air上装Win7
    Redis的安装与idea中的使用
    CAD中如何裁剪需要的区域
    Layui 使用问题汇总
    Instant Run 的操作影响到了代码,导致Android App启动闪退的问题
    Android studio百度地图demo出现230错误,key校验失败
    「小程序JAVA实战」小程序注册界面的开发(29)
    「小程序JAVA实战」小程序和后台api通信(28)
    「小程序JAVA实战」小程序多媒体组件(27)
    「小程序JAVA实战」小程序导航组件(26)
  • 原文地址:https://www.cnblogs.com/94YY/p/2199339.html
Copyright © 2020-2023  润新知