有没有办法挂接到dbx用户会话的WndProc?

背景:
dbx DataSnap使用Indy组件进行TCP通信。以最简单的形式,DataSnap服务器是一个接受连接的Indy TCP服务器。建立连接后,Indy为该连接创建一个线程,该线程处理对该连接的所有请求。

这些用户连接中的每一个都消耗资源。对于同时具有数百个连接的服务器,这些资源可能很昂贵。许多资源可以合并,但是我不想每次都需要时总是获取和释放资源。

相反,我想实现一个空闲计时器。线程完成资源处理后,计时器将启动。如果线程在计时器过去之前访问资源,则该资源仍将“分配”给该线程。但是,如果计时器在下一次访问之前过去,则资源将释放回池中。线程下次需要资源时,将从池中获取另一个资源。

我还没有找到一种方法来做到这一点。我尝试使用SetTimer,但我的计时器回调从未触发。我认为这是因为该线程的Indy WndProc没有调度WM_TIMER。我无法控制此线程的“执行循环”,因此无法轻松查看事件是否已发出信号。实际上,除非线程正在处理用户请求,否则我的该线程代码均不会执行。实际上,我希望代码在任何用户请求之外执行。

对于原始问题或替代方法建议的解决方案将同样受到赞赏。

最佳答案

我们试图使用TCP连接(没有HTTP传输,所以没有SessionManager)实现一些实现在用户线程之间共享资源的方法,但是遇到了各种各样的问题。最后,我们放弃了使用单个用户线程(设置为LifeCycle := TDSLifeCycle.Server),并在ServerContainerUnit中创建了自己的FResourcePoolFUserList(均为TThreadList)。实施仅花费了1天的时间,并且效果很好。

这是我们所做的简化版本:

TResource = class
  SomeResource: TSomeType;
  UserCount: Integer;
  LastSeen: TDateTime;
end;


当用户连接时,我们在FResourcePool中检查用户所需的TResource。如果存在,我们将增加资源的UserCount属性。用户完成后,我们递减UserCount属性并设置LastSeen。我们有一个TTimer每60秒触发一次,以释放UserCount = 0LastSeen大于60秒的任何资源。

FUserList非常相似。如果几个小时都没有看到用户,我们认为他们的连接已断开(因为如果用户空闲90分钟,我们的客户端应用会自动断开连接),因此我们通过编程方式在服务器端断开了该用户的连接,这也会减少他们对每种资源的使用。当然,这意味着我们必须自己创建一个会话变量(例如CreateGUID();),并将其在客户端首次连接时传递给客户端。客户端将每个请求的会话ID传递回服务器,因此我们知道是哪个FUserList记录。尽管这是不使用用户线程的缺点,但易于管理。

关于delphi - 陷入dbx DataSnap用户 session 的消息循环,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9010281/

10-17 01:29