竹达彩奈cos小樱:服务器开发
来源:百度文库 编辑:偶看新闻 时间:2024/05/07 16:37:03
服务器开发
总结了一些经验,现贴出于大家讨论。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连接同步管理我稍后放上来,欢迎大家讨论。 ADO连接同步管理代码,我是从应用中剥离出来的,对不起不能提供全部。供大家讨论
Unit uitSyncConnect;
Interface
Uses
Windows,
Messages,
SysUtils,
Variants,
Classes,
Contnrs,
Activex,
ADODB,
DB;
Const
csMaxQueueThread = 9;
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
rThreadTag: Integer;
rEvent: THandle;
rADOQuery: TADOQuery;
rIsCommand: Boolean;
rIsError: Boolean;
rMessage: String[255];
End;
TSyncConnect = Class(TObject)
Private
FThreadCount: Integer;
FQueue: TQueue;
FSyncManage: TSyncManage;
FLock: TRTLCriticalSection;
Public
Constructor Create(Const aQueueName: String; Const aConnectStr: String; Const aBuffer: Integer = 1024; Const aThreadCount: Integer = 5);
Destructor Destroy; Override;
Procedure PushQueue(Var aQueueItem: TQueueItem);
Published
End;
Type
TQueueThread = Class(TThread)
Private
hSyncManage: TSyncManage;
hQueue: TQueue;
hTag: Integer;
hADOConnect: TADOConnection;
Protected
Procedure Execute; Override;
Public
Constructor Create(Const aConnStr: String; Const aTag: Integer; aQueue: TQueue; aSyncManage: TSyncManage); Virtual;
Destructor Destroy; Override;
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(Const aConnStr: String; Const aTag: Integer; aQueue: TQueue; aSyncManage: TSyncManage);
Begin
Inherited Create(True);
hQueue := aQueue;
hSyncManage := aSyncManage;
Priority := tpHigher;
hADOConnect := TADOConnection.Create(Nil);
hADOConnect.ConnectionString := aConnStr;
hTag := aTag;
Resume;
End;
Destructor TQueueThread.Destroy;
Begin
Terminate;
WaitFor;
FreeAndNil(hADOConnect);
Inherited Destroy;
End;
Procedure TQueueThread.Execute;
Var
mQueueItem: PQueueItem;
Begin
While Not Terminated Do
Begin
hSyncManage.WaitFor(Integer(INFINITE)); //?T?Tμè
If Terminated Then Exit;
If hQueue.Count <= 0 Then Exit;
mQueueItem := hQueue.Pop;
mQueueItem.rThreadTag := hTag;
mQueueItem.rIsError := False;
CoInitialize(Nil);
If Assigned(mQueueItem.rADOQuery) Then
Begin
Try
mQueueItem.rADOQuery.Connection := hADOConnect;
If mQueueItem.rIsCommand Then
mQueueItem.rADOQuery.ExecSQL
Else
mQueueItem.rADOQuery.Open;
Except
On E: Exception Do
Begin
mQueueItem.rIsError := True;
mQueueItem.rMessage := E.Message;
End;
End;
End;
CoUninitialize;
SetEvent(mQueueItem^.rEvent);
End;
End;
//***********************************************************TSyncConnect*************************
Var
FQueueThread: Array[0..csMaxQueueThread] Of TQueueThread;
Constructor TSyncConnect.Create(Const aQueueName: String; Const aConnectStr: String; Const aBuffer: Integer = 1024; Const aThreadCount: Integer = 5);
Var
i: Integer;
Begin
Inherited Create;
InitializeCriticalSection(FLock);
FQueue := TObjectQueue.Create;
FSyncManage := TSyncManage.Create(aQueueName, 0, aBuffer);
If aThreadCount - 1 > csMaxQueueThread Then FThreadCount := csMaxQueueThread Else FThreadCount := aThreadCount - 1;
For i := 0 To FThreadCount Do
FQueueThread[i] := TQueueThread.Create(aConnectStr, i, FQueue, FSyncManage);
End;
Destructor TSyncConnect.Destroy;
Var
i: Integer;
Begin
EnterCriticalSection(FLock);
Try
For i := 0 To FThreadCount Do
Begin
FQueueThread[i].Terminate;
FSyncManage.Release;
FreeAndNil(FQueueThread[i]);
End;
FreeAndNil(FSyncManage);
FreeAndNil(FQueue);
Finally
LeaveCriticalSection(FLock);
DeleteCriticalSection(FLock);
Inherited Destroy;
End;
End;
Procedure TSyncConnect.PushQueue(Var aQueueItem: TQueueItem);
Var
mQueueItem: PQueueItem;
Begin
New(mQueueItem);
mQueueItem^ := aQueueItem;
mQueueItem^.rEvent := CreateEvent(Nil, False, False, Nil);
EnterCriticalSection(FLock);
FQueue.Push(mQueueItem);
LeaveCriticalSection(FLock);
FSyncManage.Release;
WaitForSingleObject(mQueueItem^.rEvent, 60000);
ResetEvent(mQueueItem^.rEvent);
CloseHandle(mQueueItem^.rEvent);
aQueueItem := mQueueItem^;
Dispose(mQueueItem);
End;
End. 下面是两个队列类的代码,高手帮忙指点指点看看有什么不对的地方,
第一个是限制容量的QUEUE,第二个是标准链表实现的QUEUE
事件是根据条件编译来决定是否使用的
unit FifoQueue;
interface
uses
Classes, Sysutils, Windows, Syncobjs;
type
TCompareQueueItemMethod = function(Item1, Item2: Pointer): Boolean;
TPointerArray = array of Pointer;
TItemEvent = procedure(Item: Pointer) of object;
TFifoQueue = class(TObject)
private
FQueueArray: TPointerArray;
FQueueLock: TCriticalSection;
{$IFNDEF SERVERMODE}
FOnPushItem: TItemEvent;
FOnGetItem: TItemEvent;
{$ENDIF}
FFirstItemIndex, FLastItemIndex: Integer;
FCount, FCapacity: Integer;
public
constructor Create(QueueLength: Integer);
destructor Destroy; override;
function PushItem(Item: Pointer): Boolean;
function GetItem: Pointer;
//function GetItems(GetNum: Integer): TPointerArray;
function FindItem(Item: Pointer; method: TCompareQueueItemMethod): Boolean;
property Count: Integer read FCount;
{$IFNDEF SERVERMODE}
property OnPushItem: TItemEvent read FOnPushItem write FOnPushItem;
property OnGetItem: TItemEvent read FOnGetItem write FOnGetItem;
{$ENDIF}
end;
PLinkNode = ^TLinkNode;
TLinkNode = record
Prior: PLinkNode;
Data: Pointer;
Next: PLinkNode;
end;
TExtendQueue = class(TObject)
private
FFirstNode, FLastNode: PLinkNode;
{$IFNDEF SERVERMODE}
FOnPushItem: TItemEvent;
FOnPopItem: TItemEvent;
{$ENDIF}
FCount: Integer;
procedure DeleteNode(node: PLinkNode);
procedure Clear;
public
constructor Create;
destructor Destroy; override;
procedure PushItem(Item: Pointer);
function PopItem: Pointer;
function GetItem: Pointer;
function FindItem(Item: Pointer; method: TCompareQueueItemMethod): Boolean;
function PopFindItem(Item: Pointer; method: TCompareQueueItemMethod): Pointer;
property Count: Integer read FCount;
{$IFNDEF SERVERMODE}
property OnPushItem: TItemEvent read FOnPushItem write FOnPushItem;
property OnPopItem: TItemEvent read FOnPopItem write FOnPopItem;
{$ENDIF}
end;
implementation
{ TFifoQueue }
constructor TFifoQueue.Create(QueueLength: Integer);
begin
FCapacity := QueueLength;
SetLength(FQueueArray, FCapacity);
FQueueLock := TCriticalSection.Create;
FFirstItemIndex := -1;
FLastItemIndex := -1;
FCount := 0;
end;
destructor TFifoQueue.Destroy;
begin
FQueueLock.Free;
FQueueArray := nil;
end;
function TFifoQueue.FindItem(Item: Pointer; method:
TCompareQueueItemMethod): Boolean;
var
i: Integer;
begin
Result := False;
if FCount = 0 then Exit;
FQueueLock.Enter;
try
for i := FFirstItemIndex to FLastItemIndex do
if method(Item, FQueueArray[i]) then
begin
Result := True;
Break;
end;
finally
FQueueLock.Leave;
end;
end;
function TFifoQueue.GetItem: Pointer;
begin
Result := nil;
if FCount = 0 then
Exit;
FQueueLock.Enter;
try
Result := FQueueArray[FFirstItemIndex];
Dec(FCount);
if FCount = 0 then
begin
FFirstItemIndex := -1;
FLastItemIndex := -1;
end
else
begin
if FFirstItemIndex = FCapacity - 1 then
FFirstItemIndex := 0
else
Inc(FFirstItemIndex);
if FCount = 1 then
FLastItemIndex := FFirstItemIndex;
end;
{$IFNDEF SERVERMODE}
if Assigned(FOnGetItem) then
FOnGetItem(Result);
{$ENDIF}
finally
FQueueLock.Leave;
end;
end;
{function TFifoQueue.GetItems(GetNum: Integer): TPointerArray;
var
ResultNum: Integer;
begin
ResultNum := Min(GetNum, FCount);
SetLength(Result, ResultNum);
FQueueLock.Enter;
try
if FFirstItemIndex < FCapacity - 1 then
FFirstItemIndex := ResultNum - 1
else
Inc(FFirstItemIndex, ResultNum);
Dec(FCount, ResultNum);
Move(FQueueArray[FFirstItemIndex]);
finally
FQueueLock.Leave;
end;
end;}
function TFifoQueue.PushItem(Item: Pointer): Boolean;
begin
Result := False;
if FCount = FCapacity then
Exit;
FQueueLock.Enter;
try
if FLastItemIndex = FCapacity - 1 then
FLastItemIndex := 0
else
Inc(FLastItemIndex);
Inc(FCount);
if FCount = 1 then
FFirstItemIndex := FLastItemIndex;
FQueueArray[FLastItemIndex] := Item;
Result := True;
{$IFNDEF SERVERMODE}
if Assigned(FOnPushItem) then
FOnPushItem(Item);
{$ENDIF}
finally
FQueueLock.Leave;
end;
end;
{ TExtendQueue }
procedure TExtendQueue.Clear;
var
tmp, node: PLinkNode;
begin
node := FFirstNode;
while Assigned(node) do
begin
tmp := node;
node := node^.Next;
Dispose(tmp);
end;
end;
constructor TExtendQueue.Create;
begin
FCount := 0;
FFirstNode := nil;
end;
destructor TExtendQueue.Destroy;
begin
Clear;
inherited;
end;
function TExtendQueue.FindItem(Item: Pointer;
method: TCompareQueueItemMethod): Boolean;
var
node: PLinkNode;
begin
Result := False;
if FCount = 0 then
Exit
else
begin
node := FFirstNode;
while Assigned(node) do
begin
Result := method(Item, node.Data);
if Result then
Break;
node := node^.Next;
end;
end;
end;
function TExtendQueue.PopFindItem(Item: Pointer;
method: TCompareQueueItemMethod): Pointer;
var
node: PLinkNode;
begin
Result := nil;
if FCount = 0 then
Exit
else
begin
node := FFirstNode;
while Assigned(node) do
begin
if method(Item, node.Data) then
begin
Result := node.Data;
DeleteNode(node);
Dec(FCount);
{$IFNDEF SERVERMODE}
if Assigned(FOnPopItem) then
FOnPopItem(Result);
{$ENDIF}
Break;
end;
node := node^.Next;
end;
end;
end;
function TExtendQueue.GetItem: Pointer;
begin
if FCount = 0 then
Result := nil
else
Result := FFirstNode^.Data;
end;
procedure TExtendQueue.DeleteNode(node: PLinkNode);
begin
if Assigned(node^.Prior) then
node^.Prior^.Next := node^.Next;
if Assigned(node^.Next) then
node^.Next^.Prior := node^.Prior;
if FCount = 1 then
begin
FFirstNode := nil;
FLastNode := nil;
end
else
begin
if node = FFirstNode then
FFirstNode := node^.Next;
if node = FLastNode then
FLastNode := node^.Prior;
end;
Dispose(node);
end;
function TExtendQueue.PopItem: Pointer;
var
node: PLinkNode;
begin
if FCount = 0 then
Result := nil
else
begin
node := FFirstNode;
Result := node^.Data;
if FCount = 1 then
begin
FLastNode := nil;
FFirstNode := nil;
end
else
begin
FFirstNode := node^.Next;
FFirstNode.Prior := nil;
end;
Dec(FCount);
{$IFNDEF SERVERMODE}
if Assigned(FOnPopItem) then
FOnPopItem(Result);
{$ENDIF}
Dispose(node);
end;
end;
procedure TExtendQueue.PushItem(Item: Pointer);
var
node: PLinkNode;
begin
if FCount = 0 then
begin
New(FFirstNode);
FFirstNode^.Data := Item;
FFirstNode^.Next := nil;
FFirstNode^.Prior := nil;
FLastNode := FFirstNode;
end
else
begin
New(node);
node^.Data := Item;
node^.Next := nil;
node^.Prior := FLastNode;
FLastNode^.Next := node;
FLastNode := node;
end;
Inc(FCount);
{$IFNDEF SERVERMODE}
if Assigned(FOnPushItem) then
FOnPushItem(Item);
{$ENDIF}
end;
end.
开发服务器的项目
怎样开发电子邮件接收服务器
web开发中的ftp服务器?
邮件服务器开发需要解决的问题
如何利用VB进行SOAP服务器和客户端开发
做J2EE开发用什么应用服务器比较方便?
FTP服务器软件名称及其开发公司的名称
什么是监控服务器,监控服务器的作用有哪些?一般应用开发中是怎么用监控服务器的?
作为J2EE的集成开发环境和服务器,请说说WebSphere有哪些特点?
不安装整个php服务器,能写代码、debug的php开发环境是什么?
请问如果要开发一个服务器-客户端的聊天软件,周期是多少?
网站开发非常之旅 服务器配置全攻略 那有免费下的?
求<asp.net服务器控件开发技术与实例>光盘源码
VFP开发扩充为局域网内的客户/服务器共享版,请各位高手指点迷津?
中文环境下开发的ASP+ACCESS网站在国内服务器上正常
2003下开发的asp.net程序移到2000服务器下可以运行吧?
JSP开发的网站对于服务器的要求是不是比ASP.net的要求高?
我要帮某公司做一个JSP网站,带数据库开发、域名申请、部署到服务器上,该开价多少?
求ASP.NET服务器控件开发技术与实例一书源码 topweb520@126.com 谢谢了
服务器---
开发一款网络游戏(如劲舞团等)并投入测试所需要的投入大概是多少?包括服务器等硬件。
谁有没有提供软件下载,电影下载的FTP服务器地址给一个用户名未开发与密码吧,有匿名的最好多谢了
谁有没有提供软件下载,电影下载的FTP服务器地址给一个用户名未开发与密码吧,有匿名的最好多谢了
我在安装.NET2003之前被告知先要安装web服务开发的组件(FrontPage服务器扩展)谁知道这组件如何安装,谢谢