DataSnap Server

DSServer1Disconnect

这个函数什么时候执行?

void __fastcall TServerContainer1::DSServer1Disconnect(TDSConnectEventObject *DSConnectEventObject)

客户端正常退出的时候,会执行,SQLConnection1->Close();

如果客户端异常退出,进程异常终止,单独的demo异常终止会执行DSServer1Disconnect,但是主框架程序异常终止为何不触发??

Project E:\AppServer\myserver.exe faulted with message: 'application-defined exception (code 0x0eedfade) at 0x75e4c41f'. Process Stopped. Use Step or Run to continue.

是你的子线程直接操作 VCL的缘故??

方式一

这样创建的Form,进程中断也正常,触发了 DSServer1Disconnect。

Application->CreateForm(__classid(Tfrmyhdl), &frmyhdl);

方式二

如果用下面的方式创建Form,进程中断就不触发DSServer1Disconnect,server就不正常了!
frmyhdl = new Tfrmyhdl(Application);
frmyhdl->ShowModal();
delete frmyhdl;

但是不能因此而改变客户端的写法吧,如果客户端突然停电,服务器难道也要异常退出?所以应该还是服务端DataSnap的问题吧

客户端不调用方法,只连接,不关闭连接,也是出现这种情况,再次验证了方式二的窗体确实有问题。

dm->SQLConnection1->Close();
dm->SQLConnection1->Params->Values["HostName"] = LabeledEdit1->Text;
dm->SQLConnection1->Params->Values["Port"] = LabeledEdit2->Text;
dm->SQLConnection1->Open();

从服务端着手研究,新建一个空白datasnap服务端,然后客户端连接不关闭连接,进程中断,服务端是好的,没有退出。

下来比较空白工程和自己写的server代码里有什么是线程不安全的?

果然,ServerContainerUnit1.cpp里的所有事件的记录日志的功能去掉就OK啦,不闪退了。

客户端异常中断后不触发DSServer1Disconnect事件,DSTCPServerTransport1Disconnect事件里也获取不到参数信息。所以最终解决方案是删除DSTCPServerTransport1Disconnect事件就可以了。

经过试验,取消ServerContainerUnit1事件就正常了,屏蔽里边的代码事件保留也不行,必须把事件代码删除完,事件为空

void __fastcall TServerContainer1::DSTCPServerTransport1Disconnect(TDSTCPDisconnectEventObject Event) 客户端两种方式都可以正常了,服务端也不退出了。

ServerContainerUnit1其他事件代码保留正常,就DSTCPServerTransport1Disconnect有问题啊!

delphi里DSTCPServerTransport1Disconnect事件正常触发,可以获取信息(TIdTCPConnection*)Event.Connection,但是在c++builder里,这个事件触发了,但是Event.Connection无法获取真实的值。

有人也发现c++builder的这个datasnap的不过。

http://codeverge.com/embarcadero.datasnap/tdstcpdisconnecteventobject-is-real-bug/1097541

In C++Builder XE2 and XE3 event handler
for TCP_connect: void __fastcall TServerContainer1::DSTCPServerTransport1Connect(TDSTCPConnectEventObject &Event)
{
Form1->ListBox1->Items->AddObject(IntToHex((int)Event.Connection,),NULL) ;
} and for TCP_disconnect void __fastcall ServerContainer1::DSTCPServerTransport1Disconnect(TDSTCPDisconnectEventObject Event)
{
Form1->ListBox1->Items->AddObject(IntToHex((int)Event.Connection,),NULL) ;
}
passed not equal objects Event.Connection in parameters the object Event.Connection is not equalent in both handlers, but for DELPHI XE2 and XE3 this handlers passes equalent objects Event.Connection and all is well
In CPU-view the real address of Event.Connection is saved in register EDX
and this handler of disconnect is very well:
void __fastcall TServerContainer1::DSTCPServerTransport1Disconnect(TDSTCPDisconnectEventObject Event)
{
TObject* PCONNECT=(TObject*)_EDX;
Form1->ListBox1->Items->AddObject(IntToHex((int)PCONNECT,),NULL) ;
} on_connect and on_disconnect passes the same objects Connection, and visually can make sessions and users lists that is "ONLINE" Edited by: matsenko vladimir on Jan , : AM

每次调用方法都会触发下面两个事件。

void __fastcall TServerContainer1::DSServerClass1Prepare(TDSPrepareEventObject *DSPrepareEventObject)

void __fastcall TServerContainer1::DSServer1Prepare(TDSPrepareEventObject *DSPrepareEventObject)

http://stackoverflow.com/questions/16602756/strange-0x0eedfade-exception-in-delphi-multi-thread-program

http://blog.devart.com/using-dac-products-in-multi-tier-db-application-development.html

声明周期选择LifeCyly/Session,dataSnapServer的内存不断增加,客户端退出了内存也不释放,而且越来越慢50个客户端*20次以后就慢了,是个隐患!这就是内存泄露?不知道delphi的应用服务器内存释放是否正常。

断开连接的4个事件都触发了。只能是内存泄露。

DSServer1Disconnect

DSServerClass1DestroyInstance

DSTCPServerTransport1Disconnect

DSServerModuleDestroy

经过试验,只连接SQLConnection1->Open();不执行任何方法,也不创建TServerMethods1Client对象,内存增长几乎忽略不计。调用了其中一个方法EchoString后就不断的吃内存了!

用delphi做了一个应用服务器,只有EchoString方法,是正常的,调用500次,内存不增长,没有内存泄露,增速是0.3M!

看来是c++builder的问题了。不知何时能解决!XE8了还是这样,每500次增长20~30M,用户那里天20M增长量。20M*60天=1.2G啊

c8新建空白工程加EchoString内存不增长,测试错误了?

FDConnection1的open放在create事件中

有FDConnection1->Open时,100次5M,500 次20M

在create事件中

没有任何FDConnection1的Open操作,无FDConnection1->Open时,500次,6M

在EchoString函数中打开并关闭连接

500次,4M

String TServerMethods1::EchoString(String value)
{
FDConnection1->Open(dm->FireDACConString);
FDConnection1->Close();
return value;
}

在EchoString函数中new打开并关闭连接,500次,4M

String TServerMethods1::EchoString(String value)
{

TFDConnection *con ;

con = new TFDConnection(NULL);
con->Open(dm->FireDACConString);

delete con;
return value;
}

把new在放在create事件中,delete在destroy事件打开并关闭连接,500次,23M,不正常了!

void __fastcall TServerMethods1::DSServerModuleCreate(TObject *Sender)
{
log("TServerMethods1DSServerModuleCreate");
// FDConnection1->Open(dm->FireDACConString);
con = new TFDConnection(NULL);
con->Open(dm->FireDACConString);

}

void __fastcall TServerMethods1::DSServerModuleDestroy(TObject *Sender)
{
FDConnection1->Close();
con->Close();
delete con;
log("TServerMethods1DSServerModuleDestroy");
}

内存问题新发现

后来发现是这个FDConnection1->Open(dm->FireDACConString);代码引起的,屏蔽此代码内存就不会无限增大。

void __fastcall TServerMethods1::DSServerModuleCreate(TObject *Sender)
{
log("TServerMethods1DSServerModuleCreate");
// FDConnection1->Open(dm->FireDACConString);

}

即使在destroy事件里关闭也不行,内存也不会释放。

void __fastcall TServerMethods1::DSServerModuleDestroy(TObject *Sender)
{
FDConnection1->Close();
}

在每个函数里执行query,然后切记关闭连接内存问题也就解决了。FDConnection1->Close();

越来越慢的问题

当客户端50数*登陆40次=2000次就开始慢了。

跟踪发现客户端

SQLConnection1->Open();不慢

TServerMethods1Client *aserver = new TServerMethods1Client(dm->SQLConnection1->DBXConnection);//不慢

aserver->log("我把日志写到服务端了");//调用第一个函数的时候就慢了,

调用后面的函数速度不慢,很快。无论第一次调用哪个函数都慢,调整函数的顺序,总之第一个函数就慢。

调用第一个函数触发服务端的事件如下

DSServerClass1Instance-Create

TServerMethods1DSServerModuleCreate
fun(我把日志写到服务端了);

应用服务器一个进程ex的线程数最大是200,上不去了。

客户端程序,正常退出,服务端的连接数减少正常,如果使用结束任务的方式结束进程,服务端的连接数未减少,这样导致进程无限制上升,积累到200个以后新的客户端就无法再连接上了。

解决办法:实时关闭,执行完一次方法就关闭连接。

DataSnap 连接池 DSServer1Disconnect的更多相关文章

  1. DataSnap 连接池

    二. DataSnap连接池 连接池 http://docwiki.embarcadero.com/Libraries/XE8/en/Datasnap.DSSession.TDSSessionMana ...

  2. DataSnap中连接池的应用

    当开发人员开始创建Delphi的DataSnap应用时很常见的数据库连接定义方式是每个数据模块建立一个连接.这样做将产生大量的数据库连接,并产生很多问题.从Delphi XE开始,EMB提供了Sess ...

  3. Delphi XE FireDac 连接池

    在开发Datasnap三层中,使用FireDac 连接  MSSQL数据库. 实现过程如下: 1.在ServerMethods 单元中放入 FDManager.FDPhysMSSQLDriverLin ...

  4. 连接SQLServer时,因启用连接池导致孤立事务的原因分析和解决办法

    本文出处:http://www.cnblogs.com/wy123/p/6110349.html 之前遇到过这么一种情况: 连接数据库的部分Session会出现不定时的阻塞,这种阻塞时长时短,有时候持 ...

  5. C3p0连接池配置

    在Java开发中,使用JDBC操作数据库的四个步骤如下:   ①加载数据库驱动程序(Class.forName("数据库驱动类");)   ②连接数据库(Connection co ...

  6. Java第三方数据库连接池库-DBCP-C3P0-Tomcat内置连接池

    连接池原理 数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”.预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去.我们可以通过设定连接池 ...

  7. common-pool2 学习:thrift连接池的另一种实现

    对象池是一种很实用的技术,经典的例子就是数据库连接池.去年曾经从零开始写过一个thrift客户端连接池.如果不想重造轮子,可以直接在apache开源项目commons-pool的基础上开发. 步骤: ...

  8. druid连接池获取不到连接的一种情况

    数据源一开始配置: jdbc.initialSize=1jdbc.minIdle=1jdbc.maxActive=5 程序运行一段时间后,执行查询抛如下异常: exception=org.mybati ...

  9. C3P0连接池配置和实现详解

    一.配置 <c3p0-config> <default-config> <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数.Default: 3 --> ...

随机推荐

  1. BD09坐标(百度坐标) WGS84(GPS坐标) GCJ02(国测局坐标) 的相互转换

    BD09坐标(百度坐标) WGS84(GPS坐标) GCJ02(国测局坐标) 的相互转换 http://www.cnphp6.com/archives/24822 by root ⋅ Leave a ...

  2. ZOJ3640Help Me Escape(师傅逃亡系列•一)(数学期望||概率DP)

    Background If thou doest well, shalt thou not be accepted? and if thou doest not well, sin lieth at ...

  3. Java并发--阻塞队列

    在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList),这些工具都为我们编写多线程程 ...

  4. BZOJ2160 拉拉队排练【Manacher】

    Description 艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了.拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛.所以作为拉拉队队长的楚雨荨同学知道,帮助篮球队训 ...

  5. Orders

    The stores manager has sorted all kinds of goods in an alphabetical order of their labels. All the k ...

  6. js 时间date格式化

    js中没有类似java中的DateFormat类来处理日期格式化,可以自己写一个: var newDate=new Date(); var year=newDate.getFullYear(); va ...

  7. 《DSP using MATLAB》示例Example 8.20

    %% ------------------------------------------------------------------------ %% Output Info about thi ...

  8. 【DUBBO】dobbo的application的配置项

    Dubbo:application的配置项[一]:配置项 <dubbo:application name="服务名字" owner="拥有者" organ ...

  9. vertica从其它表迁移数据到新表(insert into 语句使用方法实例)

    版权声明:本文为博主原创文章.博主同意自由转载. https://blog.csdn.net/tx18/article/details/26585649 #例:迁移微博用户数据. 因为源表weiboF ...

  10. php系统函数-----数组函数