【DMQ引擎】-DMQ多进程插件引擎服务平台介绍

写过服务端项目的程序员可能都有非常痛苦的经历,服务端经常奔溃,无从查起。的确一个服务端要稳定下来要经过长期的积累,不停的测试,调试,发现问题,解决问题。这个周期可能很长,几个月,甚至以年计算。许多企业,公司可能经不起这样的折腾。

经过几个版本的改造和沉淀,现在推出一个基于DIOCP3的商业化服务端方案。先上一种设计蓝图。

271303490939128

就想上图看到的,服务端的逻辑插件可以是任何一种语言来扩充。而且同一种逻辑进程可以多开,服务器进行平衡调度。意思就是说其中一个进程奔溃,不会影响到后续的逻辑处理。他们还可以分布在不同的服务器上面。通信部分完全可以独立开来。自由去扩展逻辑插件。

【DIOCP应用案例】-案例2(无毒公主)

案例2<无毒公主>

服务端应用场景:

金融行业交易行情、交易控制指令发布推送服务器。主要是要稳定和快速,对负载要求不高。日常在线20个左右。服务器和客户端都用的diocp实现的iocp异步模式。由于是金融类的应用,对稳定性和推送实时性有非常高的要求(关键时候如果指令延时长了,就会损失真金白银),而一路跟着diocp1走到现在diocp3稳定一年多了 ,各方面的表现完全满足需求。

公司名称:

某金融投资公司

DIOCP版本:

从diocp1到DIOCP3 <自定义的编码器>

QQ昵称:

五毒公主(782834)

建议与问题:

我现在这个还只是一个非常小规模的应用,但是有不同的客户端(指令控制端、管理员端、交易终端)会登录到系统,在不同的客户端多了以后 协议就会多很多。 现在是在在一个编码解码器上按命令字来区分再进行业务层的解析。 虽然能满足需求。但是总觉得 如果要做非常庞大和复杂的系统的话 ,协议的管理将非常麻烦。 所以觉得如果可以一个服务器开放多个端口,每个端口有自己的在线列表,不同的客户端登录到不同的端口、应用不同的编码解码器,同时又能统一管理(应为不同的客户端之前需要数据交、转发)这样就是极好的。

 

==========================================

DIOCP官方社区|MyBean官方社区

http://diocp.wedelphi.com/

==========================================

【DIOCP应用案例】-案例1(Tiger)

2014101153544361

DIOCP是Delphi下进行IOCP服务端通讯开发的一个非常好的开源框架,稳定、高效并且使用起来十分简单。 自己两个多月之前因为需要使用Delphi开发一个TCP服务端,当时也是到处爬文,希望找到一个稳定且好用的IOCP开源框架,整整一周的时间,看了很多,也对比了很多,最后选择了DIOCP,现在服务器端正式版本已经上线运行了36天的时间了,所有运行一切稳定,无论是CPU占用、内存使用还是通信稳定性,DIOCP的表现真的没有让我失望,表现得非常优秀。

服务器环境:
OS:Windows Server 2003
CPU:Intel 双核      内存:2G
网络带宽:5M
网络类型:BGP
实际性能数据:
程序用户同时在线数:1200 – 1300之间   峰值:1511(此峰值为真实用户同时在线数,不是理论性能峰值,目前的用户数只有这些,自己测试的时候,连接数测试过5K,也同样运行稳定)。
服务器端运行到发文时已经36天多了,内存峰值也只有76M,CPU占用一直都稳定在10%以下,应该说各项指标都非常的好,非常满意。

QQ:
Tiger

 

 

==========================================

DIOCP官方社区|MyBean官方社区

http://diocp.wedelphi.com/

==========================================

【DIOCP知识库】连接上下文TIocpClientContext

【概述】

     该类管理远程连接,每一个远程连接会对应一个该类的实例,开发时可以通过继承该类,扩展属性,可以存储更多的连接信息,可以重写OnRecvBuffer方法进行数据逻辑的处理

 

【字段/属性说明】

  • property RemoteAddr: String read FRemoteAddr;

说明:远程连接IP。

 

  • property RemotePort: Integer read FRemotePort;

说明:远程连接端口。

 

  • property SocketHandle: TSocket read FSocketHandle;

说明:连接套接字.

 

【方法说明】

  • procedure DoCleanUp;virtual;

说明: 该方法从对象池中获取一个对象时(TIocpTcpServer.getClientContext)执行该方法,进行相关资源的清理,在该实例不再需要,放回到连接池时(TIocpTcpServer.releaseClientContext)也会执行该方法,该方法同时只会一个线程访问和执行。

 

  • procedure PostNextSendRequest; virutal;

说明:该方法在发送请求得到响应完成并成功(TIocpSendRequest.HandleResponse),会再次调用该方法可以进行下一个请求的发送,如果响应中发现GetLastError不为0或者服务关闭已经停止则不会执行该方法

 

  • procedure OnRecvBuffer(buf: Pointer; len: Cardinal; ErrCode: WORD); virtual;

说明:如果接收到远程数据时会触发该函数的执行,该方法在响应投递的接收数据的请求(TIocpRecvRequest.HandleResponse)中调用,如果响应中发现GetLastError不为0或者服务关闭已经停止则不会执行该方法。

 

 

==========================================

DIOCP官方社区|MyBean官方社区

http://diocp.wedelphi.com/

==========================================

【DIOCP知识库】-粘包的处理

什么是粘包:

   第一次发送  12345, 第二次发送abcde, 底层socket可能会一次性进行发送12345abcde,或者对方可能一次性进行了接收,那接收的时候,你可能想分两次接收才对,第一次接受到12345, 第二次想接收abcde,但是事与愿违,一次就接收完了,这就是粘包的问题。需要自己处理。

 

怎么样处理粘包:

  常见的方法是在包数据的前面加长度比如我先发送一个字节代表长度5 然后再发数据包12345, 这样接收的时候,先读数据包长度,然后再获取包的数据,这样就可以处理粘包问题了。

diocp3的StreamCoder,可以让你直接发送TStream对象,不需要处理粘包的问题。接收到的数据对象就是一个TStream对象

==========================================

DIOCP官方社区|MyBean官方社区

http://diocp.wedelphi.com/

==========================================

【杂谈接口】接口对象的生命周期-对象所占用的内存块清理

【概述】

相信经常使用接口的朋友们,经常碰到访问违规异常(Access violation),很多情况下无法理解,认为是编译器的Bug,然后去绕开它,不追其根源,把责任推给IDE,推给编译器(其实本人以前也经常这样想)。其实每个异常都是有原因的,碰到这种问题不要绕开,如果目前无法解决,至少要清楚的知道它出现的起因,不放过每一次追根到底的机会。这才是做程序员的应有的心态。(好像有点扯远了…)

 

【问题描述】

今天公司外包模块中,外包人员反应出现一个很奇怪的问题,说模块中无故出现了AV异常。调试果然如此,而且每次都能出现,每次都能出现的异常就好解决,

最初的代码如下:

一个点击按钮事件中包含如下一段代码:

 

begin
  ....
  (TmBeanFrameVars.GetBean('ef_pcy_frmTree'as INormalSelector).executeSelect(lvPass);
  ....
end;

这样程序在退出函数的时候引发了一个AV异常(end;运行之后),这时候一般对接口不了解的都无从下手。也无从下手进行调试。

 

【问题分析】

首先上面这句简单的访问其实会出现接口的临时变量,而这个变量在函数退出的时候会执行清理,因为executeSelect函数中释放了插件的实例,然后清理临时接口变量时会触发接口对象的__release方法。这个时候引发的一个异常。

我改造一下代码,让错误在函数退出之前出现,完整代码如下。

I`VNO]}GF`0}M_PHZR9C2{U

我用两个局部变量,这样改造后,在执行lvIntf := nil的时候就会出现AV错误。

image

我顺便把executeSelect代码贴一下,可以看到这个插件是一个窗体对象实例。在执行这个函数里面会把窗体显示,然后进行了释放,然后退出了函数。

 

大概的原因明白后,我们调整下代码,代码如下:

PFRPD@W3BOX1E[R2B~V[~K9

注意红色部分,选取完后(释放实例后),然后马上清理接口变量,这个时候,其实内存块应该还是完整的(个人推测),所以清理时不会出现访问违规异常。

 

下面我来做个调试证明我的推测

R7$@CSJ6K@)E74)1XGHER@V

看红色框出来部分,两个接口变量在释放完后,和之前的指向的内存块中值是一样的(我只获取了一个值,其实可以进行完整对比),然继续执行。

{8FA%_B][VZU%_SCWT7%V@U

在看看红色部分,这个时候(其实执行玩cdsOrgan.Append就出现了),lvIntf指向的内存块已经被清理了,因为有新的内存申请。所以后面在清理lvIntf := nil的时候出现访问违规错误。

 

好了到了这个时候,我们应该发现引发异常的真正原因了:在清理接口变量时,访问了一块不可预知的内存块,所以导致了访问违规错误。所以请大家在使用接口过程中注意接口的清理工作。

 

*认真阅读会收获更多。

 

==========================================

DIOCP官方社区|MyBean官方社区

http://diocp.wedelphi.com/

==========================================