第4篇quick中间件服务端高级编程_第1页
第4篇quick中间件服务端高级编程_第2页
第4篇quick中间件服务端高级编程_第3页
第4篇quick中间件服务端高级编程_第4页
第4篇quick中间件服务端高级编程_第5页
已阅读5页,还剩304页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、QuickBurro 从入门到精通 - 中间件服务端高级编程所有© 樵夫软件开发目录一、服务端插件框架原理31.1 、插件框架的由来31.2 、服务端插件的种类41.3 、数据容器类与序列化转换51.4 、插件调用的激发条件91.5 、插件的线程模式101.6 、插件的驻留内存形式111.7 、插件延迟卸载处理111.8、插件编的 API 函数111.9 、插件间共享数据的方法121.10 、插件的安全性12二、C/S 三层服务插件开发132.1 、C/S 三层服务插件的接口规范132.2 、C/S 三层服务插件模板文件132.3、C/S 三层服务插件的.202.4、在客户端程序里调

2、用插件功能21三、Web 服务插件开发233.1 、QuickBurro 中的虚拟动态页面233.2 、Web 服务插件的接口规范243.3 、Web 服务插件模板文件263.4 、Web 服务插件的部署方法323.5 、传统 Web 表单形式调用插件示例333.6 、AJAX 形式调用Web 服务插件示例373.7 、在非网页客户端里调用 Web 服务插件示例413.8 、ISAPI 标准的Web 服务插件48四、移动服务插件开发524.1 、Multipart 格式的Web 请求534.2 、移动服务插件的接口规范534.3 、移动服务插件模板文件544.4 、移动服务插件的客户端调用方法

3、59五、Lazarus 服务插件开发645.1、Lazarus 服务插件接口规范641 / 309QuickBurro 从入门到精通 - 中间件服务端高级编程所有© 樵夫软件开发5.2 、Lazarus 服务插件模板文件645.3 、TLazRPC 远过程调用控件695.4 、Lazrus 服务插件及调用示例70六、WebSocket 服务插件开发736.1 、QuickBurro 的 WebSocket 服务746.2 、在 WebSocket 连接上实现的远过程调用836.3 、WebSocket 服务插件的接口规范836.4 、WebSocket 服务插件模板文件836.5 、

4、WebSocket 插件调用示例86七、计划任务插件开发897.1 、可执行文件形式的计划任务模块897.2 、DLL 形式的计划任务插件937.3 、驻留式计划任务示例95八、服务端 API 函数详解1008.1、ADO 数据库连接池接口 API1028.2、ADO 数据库重要功能接口 API1118.3 、UniDAC 数据库连接池接口 API1208.4 、FireDAC 数据库连接池接口 API1298.5 、中间件对象管理接口 API1378.6 、消息传输功能接口 API1518.7 、Web 会话管理接口 API1708.8 、WebSocket 会话管理接口API1968.9

5、、数据共享交换接口 API2218.10 、通用对象池管理接口 API2358.11、HTTPS接口 API2448.12、杂项功能接口 API2518.13、第平台接口API274九、后记3082 / 309QuickBurro 从入门到精通 - 中间件服务端高级编程所有© 樵夫软件开发QuickBurro 中间件服务端高级编程一、服务端插件框架原理1.1、插件框架的由来从新版资料第一篇中的第 5 章“三层架构模块化技术”我们可以看出,将中间件分为“ 主程序、业务逻辑部件集合、 工具”三大部分是QuickBurro 中间件系统所推崇的模块化实现方案,它将带来中间层软件规模的可控化、

6、服务的可配置能力、模块的可复用性、维护的方便性等好处,对降低开发与运维成本、降低项目开发风险、提高软件质量等方面也有很明显的促进作用。而“服务端插件框架”技术,是上述分模块方案的实现方法。具体来说,就是将中间层软件主程序设计为一种可轻松和拔除模块的容器程序,而将业务处理部分设计成一系列的可到主程序及从主程序拔除的模块程序,形象地说,类似于带了无数扩展槽的电子设备,可以将遵循扩展槽接口标准的电子线路板主设备以进行功能增强、而将电子线路板从主设备插槽里拔掉来实现功能的卸除。对于 QuickBurro中间件,在基于Windows 系统的环境下,中间件主程序是一个标准Windows 服务程序(.exe

7、),而业务处理模块则是一系列的动态库(.dll),而所谓的“/拔除”动作,可以使用台管理工具等实现。由中间件服务程序的技术实现角度来看,服务端插件框架既要满足轻松/拔除的需要,更要满足“为客户端提供良好的并发服务”这一总任务的需要,所以,插件框架必须与网络通信、并发任务处理等部分有很好的协作,框架运行流程上遵循中间件工作主流程的。经过我们大量的研究与实践, QuickBurro中间件最终采用了下图所示这样的技术实现方案,按下图尝试走一遍功能调用交互过程,就可以理解此插件框架的工作原理。3 / 309QuickBurro 从入门到精通 - 中间件服务端高级编程所有© 樵夫软件开发(1)

8、 、客户端程序通过 TCP 或 HTTP/HTTPS 通信向中间件发起功能服务请求(2) 、服务端通信程序接收到来自客户端的请求后,将任务压入队列,然后再分配工作线程来处理任务(3) 、工作线程从任务队列弹出请求任务,根据调用对象标识找到服务端插件,加载、传入参数、执行(4)、服务端插件根据传入的参数及预先编制的处理业务逻辑(5)、业务逻辑处理完成后,插件将结果返回给工作线程,工作线程再将处理结果压入应答任务队列(6)、中间件调度分配应答反馈工作线程,然后此工作线程再从应答任务队列中取出应答数据(7)、应答反馈工作线程通过 TCP 或 HTTP/HTTPS 通信向调用发起的客户端应答数据显然,

9、服务端插件框架的实现过程,是与中间件的网络通信、任务调度、线程池、任务队列等算法或数据结构紧密相关的,对外提供一种简洁的插拔式接口,而内部实现则相对复杂、较难实现的。当然,假如您理解了服务端插件框架的原理,而直接使用QuickBurro 中间件、不是写底层去实现这一切的话,就不必与这些纠结在一起的技术问题打交道直接使用插件框架、编写一下插件并调用,就可以了。1.2、服务端插件的种类上节这样的服务端插件框架在 QuickBurro 中间件主服务中存在多个实例,即 C/S 三层服务插件框架、Web 服务插件框架、WebSocket 服务插件框架、移动开发服务插件框架等,它们的实现原理都一样,只是在

10、接口规范上存在一些很小的差异。然后,与这些插件框架实例相对应,服务端插件也就分为如下几类:1)、C/S 三层架构服务插件这是一类服务于 C/S 三层客户端的服务端插件,是QuickBurro 中间件最早支持的一类插件。这类插件通过中间件的TCP 任务端口接收调用任务后再被调用执行;并且,它们需要到中间件上才能被客户端调用;这类插件通过传递TQBParcel 形式的参数包和出口参数包的形式来交换数据;支持单线程/多线线程模式;可以设置来确保安全性;支持驻留/非驻留运行方式;支持同步/异步用。除了被客户端调用之外,这类插件还支持以计划任务、触发消息等方式进行触发执行。2)、Web 服务插件这是一类

11、通过 HTTP/HTTPS 协议调用的服务端插件。这类插件也可为驻留内存以应对高强度频繁调用的需求,但不时也能直接调用(但不驻留内存);另外,对它们的调用通过自动的“虚拟动态页面”URL 的形式进行;调用时参数交换通过 Web 表单、Json、Xml 等方式进行;这类插件全部为多线程方式调用,支持同步/异步调用。3)、WebSocket 服务插件这是一类专门为WebSocket 长连接提供的服务端插件,客户端也通过自动的“虚拟动态页面”URL来作为标识进行调用。这类插件像 Web 插件一样,可为驻留内存以应对高强度频繁调用的需求,但不时也能直接调用(但不驻留内存);调用时参数交换一般通过 Js

12、on、Xml 等方式进行。这类插件全部为多线程用,当然也支持同步/异步调用。4)、移动服务插件对于 Delphi 多设备应用程序开发的支持(即 FireMonkey 架构下的应用开发支持)而专门实现的一类服务端插件是一种特殊的 Web 服务插件,即通信协议上采用 HTTP/HTTPS,但交换信息的封装上采用万能容器类 TMBParcel,即,TMBParcel 的传入数据包转换为Multipart 格式的Web 表单后经由 HTTP/HTTPS 通信来实现任务的提交,而结果则通过输出参数包对象封装,然后转换为二进制流,返回给多设备应用程序客户端。由于其数据交互的二进制数据形式,故在基于 HTT

13、P 协议进行通信时,安全性比一般基于 Json/Xml 数据的方式要好。这类插件也全部为多线程用、也可为驻留内存或不。4 / 309QuickBurro 从入门到精通 - 中间件服务端高级编程所有© 樵夫软件开发5)、FreePascal 服务插件另外,QuickBurro 中间件中又以“移动服务插件”类似的方式提供 FreePascal 服务插件,专门为 Free Pascal客户端(比如 Lazarus 编写的客户端)提供各种通用/的业务逻辑处理服务,它们同样通信协议上采用HTTP/HTTPS,但交换信息的封装上采用万能容器类 TLazParcel。这类插件全部为多线程用、也可为

14、驻留内存或不。1.3、数据容器类与序列化转换无论以怎么样的数据格式进行客户端/中间层交互,所传输的信息总是需要转换为流式数据的形式进行。一般地,以容器类特有的方式组织的数据转换为流式数据的过程,称为序列化,反之则叫反序列化(或叫对象化)。在客户端调用服务端插件、或插件编写的过,经常会碰到各种序列化/反序列化的场景,故这是比较重要的编程技巧,建议大家掌握。1)、万能容器类的序列化/反序列化lTQBParcel 对象序列化方法序列化到流对象function SaveToStream(var aStream: TMemoryStream): boolean;序列化到文件function SaveTo

15、File(FileName: String): boolean;序列化到字符串缓冲function SaveToString(var aStr: Ansistring): boolean;带前导长度的序列化到字符串缓冲function SaveToStringWithLength(var aStr: Ansistring): boolean;加密序列化到流对象function EncryptToStream(var aStream: TMemoryStream): boolean;Zip 压缩序列化到流对象function ZipToStream(var aStream: TMemoryStr

16、eam): boolean;Zip 压缩序列化到文件function ZipToFile(FileName: string): boolean;LZO 压缩序列化到流对象function LzoToStream(var aStream: TMemoryStream): boolean;LZO 压缩序列化到文件function LzoToFile(FileName: string): boolean;LZO 压缩序列化到字符串缓冲function LzoToString(var Str: ansistring): boolean;lTQBParcel 对象反序列化方法从流对象反序列化functi

17、on LoadFromStream(aStream: TMemoryStream): boolean;从文件反序列化function LoadFromFile(FileName: String): boolean;从字符串缓冲反序列化function LoadFromString(aStr: Ansistring): boolean;从全局内存区反序列化5 / 309QuickBurro 从入门到精通 - 中间件服务端高级编程所有© 樵夫软件开发function LoadFromMemory(MemPtr: Pointer): boolean;从全局内存块反序列化function L

18、oadFromGlobalMem(MemPtr: integer): boolean;从流对象并反序列化function DecryptFromStream(aStream: TMemoryStream): boolean;从流对象 ZIP 解压并反序列化function UnzipFromStream(aStream: TMemoryStream): boolean;从文件 ZIP 解压并反序列化function UnzipFromFile(FileName: string): boolean;从流对象 LZO 解压并反序列化function UnlzoFromStream(aStream:

19、 TMemoryStream): boolean;从字符串缓冲 LZO 解压并反序列化function UnlzoFromString(Str: ansistring): boolean;从文件 LZO 解压并反序列化function UnlzoFromFile(FileName: string): boolean;与TQBParcel 对象类似,多设备应用开发中使用的TMBParcel 对象和Lazarus 应用开发中使用的TLazParcel对象,其序列化/反序列化的处理也类似,各有一系列方法,用法很简单,不再赘述。2)、数据集的序列化/反序列化lTClientDataset 的数据集序列

20、化方法数据集序列化到流对象procedure SaveToStream(Stream: TStream; Format: TDataPacketFormat = dfBinary);数据集序列化到文件procedure SaveToFile(const FileName: string = '' Format: TDataPacketFormat = dfBinary);lTClientDataset 的数据集序反序列化方法从流对象反序列化数据集procedure LoadFromStream(Stream: TStream);从文件反序列化数据集procedure LoadF

21、romFile(const FileName: string = '');lTMBTable/TQBMemTable 的数据集序列化方法数据集序列化到流对象function SaveToStream(aStream: TMemoryStream): boolean;数据集序列化到文件function SaveToFile(aFileName: string): boolean;lTMBTable/TQBMemTable 的数据集序反序列化方法从流对象反序列化数据集function LoadFromStream(aStream: TMemoryStream): boolean;从

22、文件反序列化数据集function LoadFromFile(aFileName: string): boolean;6 / 309QuickBurro 从入门到精通 - 中间件服务端高级编程所有© 樵夫软件开发在远过程调用期间及服务端插件与客户端调用方交互期间,当需要进行数据集形式的时,这些数据集与流对象之间的转换很常见。其他内存表对象如 FDMemTable 之类,其序列化/反序列化处理大同小异,另外,也可以先与TClientDataset 进行转换,再由TClientDataset 作流化处理。3)、Json 对象的序列化/反序列化QuickBurro 中 Json 对象TQB

23、Json/TMBJson/TLazJson 进行序列化/反序列化处理过程,就是将 Json 对象转换为字符串/流对象/文件,或者反向由字符串/流/文件生成 Json 对象。这种转换处理方法在进行 JsonRPC 调用时的服务端插件编经常需要使用:l序列化方法序列化为字符串(不含回车换行制表符) function ToString (): Ansistring ; overload; override; 序列化为字符串(含回车换行制表符)function ToString2 (indentFactor : integer): Ansistring; overload;序列化为字符串(含回车换行制

24、表符,带缩进)function ToString3 (indentFactor, indent : integer): Ansistring; overload;序列化为流数据function SaveToStream(aStream: TStream; OutFormat: integer): boolean;序列化到文件function SaveToFile(aFilename: string; OutFormat: integer): boolean;序列化到包裹对象的字段function SaveToParcel(aQBParcel: TQBParcel; GoodsName: Ans

25、istring; OutFormat: integer): boolean;l反序列化方法从字符串反序列化为 Json 对象constructor Create (s : Ansistring); overload; 从流数据反序列化为 Json 对象constructor Create (aStream: TStream; Bytes: integer); overLoad;从文件反序列化为 Json 对象constructor Create (aFilename: string; FailIfNoFile: boolean); overload;从包裹对象字段数据反序列化为Json 对象c

26、onstructor create (aQBParcel: TQBParcel; GoodsName: Ansistring); overload;4)、XML 数据的序列化/反序列化Delphi 中处理 XML 数据的常用对象是 IXMLDocument,可以用以下方法进行序列化/反序列化处理:l 序列化方法序列化为流数据procedure SaveToStream(const Stream: TStream);序列化到文件procedure SaveToFile(const AFileName: DOMString);序列化为字符串procedure SaveToXML(var XML:

27、DOMString); overload; procedure SaveToXML(var XML: WideString); overload; procedure SaveToXML(var XML: UTF8String); overload;7 / 309QuickBurro 从入门到精通 - 中间件服务端高级编程所有© 樵夫软件开发l 反序列化方法从流数据反序列化procedure LoadFromStream(const Stream: TStream; EncodingType: TXMLEncodingType = xetUnknown);从文件反序列化procedu

28、re LoadFromFile(const AFileName: DOMString);从字符串反序列化procedure LoadFromXML(const XML: AnsiString); overload; procedure LoadFromXML(const XML: DOMString); overload;XmlDOC.pas 单元中的反序列化函数,由文件、字符串等创建IXMLDocument 对象:function LoadXMLDocument(const FileName: DOMString): IXMLDocument; function LoadXMLData(co

29、nst XMLData: DOMString): IXMLDocument; overload; function LoadXMLData(const XMLData: AnsiString): IXMLDocument; overload;5)、常用的转换函数在中间件的VCLSDK、FMXSDK 下,还存在若干实用函数库单元,其中包含有各种数据容器之间、容器与流对象/内存块/字符串之间的实用转换函数,请各位适当熟悉一下,编方便:lVclsdkqbcommon.pas 下字符串与流对象之间的转储procedure Str2Stream(Str: Ansistring; var aStream:

30、 TMemoryStream);procedure Stream2Str(aStream: TMemoryStream; var aStr: Ansistring);字符串与文件之间的转储function Str2File(Str: Ansistring; aFileName: string): boolean; function File2Str(aFileName: string; var Str: Ansistring): boolean; 字符串缓冲与 Cds 数据集的转换procedure Str2Cds(Str: Ansistring; var aCds: TClientDatas

31、et);procedure Cds2Str(aCds: TClientDataset; Fmt: TDataPacketFormat; var aStr: Ansistring);字符串缓冲与包裹对象的转储procedure Str2Parcel(Str: Ansistring; var aParcel: TQBParcel); procedure Parcel2Str(aParcel: TQBParcel; var aStr: Ansistring);Recordset 中的 Blob 字段转存到流function blob2stream(Rs: _RecordSet; FieldName:

32、 string; aStream: TMemoryStream): boolean;Variant 与流对象之间的转换function VariantToStream (const v: OleVariant; Stream: TMemoryStream): boolean; function StreamToVariant(Stream: TMemoryStream; var v: OleVariant): boolean;RecordSet 对象与流对象之间的转换function RecordsetToStream(const Recordset: _Recordset; var Stre

33、am: TMemoryStream; var error: string): boolean; function StreamToRecordset(Stream: TMemoryStream; var RecordSet: _Recordset): boolean;TParam 对象与包裹对象的转换function ParamToParcel(AParam:TParam; AParcel: TQBParcel; ParamDir: Byte):Boolean; function ParamFromParcel(AParam:TParam; AParcel: TQBParcel):Boolea

34、n;数据集对象之间的转换function CreateAdoDatasetAs(const SourceDS: TADODataset): TAdoDataset; function DatasetToCdsData(aDataset: TDataset): OleVariant;8 / 309QuickBurro 从入门到精通 - 中间件服务端高级编程所有© 樵夫软件开发function GetCdsFromAdo(aAdoDataset: TAdoDataset; aCds: TClientDataset): boolean;ADO 数据集转内存表function Adods2T

35、ab(aAdoDataset: TAdoDataset; aTab: TMBTable2): boolean;lVclsdkLazPluginApi.pas 下TQBMemDataset 数据集与 TClientDataset 数据集间的转换function Mds2Cds(aMds: TQBMemDataset; aCds: TClientDataset): boolean; function Cds2Mds(aCds: TClientDataset; aMds: TQBMemDataset): boolean;TQBMemDataset 数据集与 ADO 数据集之间的转换function

36、Adods2Mds(aAdoDataset: TAdoDataset; aMds: TQBMemDataset; var Error: string): boolean; function Mds2Adods(Mds: TQBMemDataset; AdoDataset: TAdoDataset): boolean;TQBMemDataset 数据集与 Json 之间的转换function MDS2Json(Mds: TQBMemDataset; aJson: TQBJson): boolean; function Json2MDS(aJson: TQBJson; Mds: TQBMemDat

37、aset): boolean;TQBMemDataset 数据集与流对象之间的转换function MDS2Stream(Mds: TQBMemDataset; aStream: TMemoryStream): boolean; function Stream2MDS(aStream: TMemoryStream; Mds: TQBMemDataset): boolean;ADO 数据集与 Json 之间的转换function Adods2Json(aAdoDataset: TAdoDataset; aJson: TQBJson): boolean;function Adods2Stream(

38、aAdoDataset: TAdoDataset; aStream: TMemoryStream): boolean;TClientDataset 数据集与其他对象之间的转换function Cds2Json(Cds: TClientDataset; aJson: TQBJson): boolean;function Cds2Stream(Cds: TClientDataset; aStream: TMemoryStream): boolean; function Tab2Cds(aTab: TQBMemTable; aCds: TClientDataset): boolean; functi

39、on Cds2Tab(aCds: TClientDataset; aTab: TQBMemTable): boolean;ADO 数据集与 TQBMemTable 之间的转换function Adods2Tab(aAdoDataset: TAdoDataset; aTab: TQBMemTable): boolean; function Tab2Adods(aTab: TQBMemTable; AdoDataset: TAdoDataset): boolean;TQBMemTable 与 Json 之间的转换function Tab2Json(aTab: TQBMemTable; aJson:

40、 TQBJson): boolean; function Json2Tab(aJson: TQBJson; aTab: TQBMemTable): boolean;TQBMemDataset 与 TQBMemTable 之间的转换function Mds2Tab(aMds: TQBMemDataset; aTab: TQBMemTable): boolean;lVclsdk adods2json.pas 下ADO 数据集与流对象间的转换function ads2LazStream(ads: TAdoDataset; aStream: TMemoryStream): boolean; funct

41、ion LazStream2ads(aStream: TMemoryStream; ads: TAdoDataset): boolean;ADO 数据集与文件之间的转储function ads2LazFile(ads: TAdoDataset; aFileName: string): boolean; function LazFile2ads(aFileName: string; ads: TAdoDataset): boolean;1.4、插件调用的激发条件服务端插件在创建并部署到中间件服务端之后,根据插件类别的不同,会在不同的外部条件下被调用9 / 309QuickBurro 从入门到精通

42、 - 中间件服务端高级编程所有© 樵夫软件开发执行,通常表现为以下几种情况:1)、被客户端调用时当 VCLSDK 下的TDllPlugin 控件、TQBHttps 控件、以及“QuickBurro Extended”组件面板下基于服务端插件封装的扩展控件调用了服务端插件模块中的方法时,服务端插件会被中间件的工作线程加载内存、调用执行指定的方法。2)、被模块触发器触发调用模块触发器之后,当指定的触发消息被中间件接收到后,就会分配一个工作线程加载触发器时指定的插件,并调用其导出函数。3)、计划任务条件满足时调用当中间件启动服务时,为“启动服务时调用”的计划任务会被自动调用;当中间件即将停

43、止服务之间,为“停止服务时调用”的计划任务会被自动调用;而为周期执行、某时间点执行等的计划任务插件,则会在时间点上被中间件工作线程调起并执行其导出函数。4)、被周边插件调用服务端插件可以主动调用其他周边插件的功能,以实现功能复用。1.5、插件的线程模式插件有多线程和单线调用模式。C/S 三层服务插件在插件时,可以指定这种线程模式。对于其他类型的插件,全部以多线程模式进行调用。插件功能的调用都是由中间件服务所分配的工作线程进行的,所谓多线程模式,就是指同一时刻可能存在多个工作线程对同一插件进行功能调用,而单线程模式,系统确保同一时刻只能存在一个调用它的工作线程,不存在并发调用的情景;对于多线程模

44、式的插件,编写时务必注意临界、全局变量等的防处理,可以不用全局变量的,尽量不要用,而单线程插件,则可以不用担心并发导致出错问题;总体效率而言,多线程模式明显要高于单线程模式;对于一些特殊的需要排队执行的功能,多线程不合适,务必使用单线程模式实现,比如业务挂号之类。除了在 C/S 三层服务插件时指定线程模式外,对于驻留内存的插件,应用程序员也可以通过定义全局临界区变量来自行处理线程模式,比如,预加载的Web 插件(驻留内存),一般外部来看是多线程执行,10 / 309QuickBurro 从入门到精通 - 中间件服务端高级编程所有© 樵夫软件开发但您可以在内部定义临界区,调用时通过临界

45、区来确保某些方法的串行执行,起到单线程模式的效果。EnterCriticalSection(Cs); LeaveCriticalSection(Cs);1.6、插件的驻留内存形式有两种功能需求要求插件一直驻留在内存中,而不要从内存卸载:一是运行过程需要保存中间状态; 二是插件被调用的频率非常高、需要减少调进调出的次数。当插件随中间件服务启动而被一直驻留内存后,就可以通过定义使用全局变量的形式来保存功能执行的中间态,插件也被经常地调进调出内存而影响运行效率;而对于非驻留形式的插件,一般是被调用时才被调入内存运行,功能调用完成后,又会从内存中卸载。驻留内存的插件占用内存,而非驻留内存的插件只在被调

46、用时占用内存。可以在QuickBurro 中间件的服务管理器的“插件”页面插件,指定“加载模式”为常驻内存或即时加载;对于 Web 服务插件,为“预加载”形式的插件就是指定为驻留内存,不则指不驻留内存。1.7、插件延迟卸载处理对于即时加载的插件,由于可能会导致频繁的调进调出而影响运行效率、降低系统稳定性,因此,我们在实现插件框架时实现了一种有效的技术措施来减少调进调出的次数,那就是所谓“插件延迟卸载”技术,即在插件需要从内存卸载时加入一定的,如在时段内有新的调用请求,则不用再从外部加载时段内不再有新的调用请求,则此插件才而直接调用、而卸载延迟在新的调用结束后重新开始,如在正式从内存中作卸载处理

47、。采用“插件延迟卸载”技术之后,对于频繁调用但又未设置为驻留内存的插件(有时管理员或应用程序员也无法有些插件的调用频度,而未将它们设置为驻留内存),可以显著减少调进调出内存的次数,有效提高运行速度及稳定性;当然,此技术使用之后,插件的动态更新可能会因插件还未卸载而出现失败,需要重试才能,对此,应用程序员或管理员应有思想准备。1.8、插件编的 API 函数QuickBurro 的服务及公共服务插件除了为客户端提供相对通用的各种中间层功能服务之外,还以回调函数的形式向周边其他服务端插件提供API 服务,这些API 函数库定义在VCLSDK 目录下的如下这些单元中,编写服务端插件时,直接 Uses

48、它们,就可以使用其中的 API 函数:11 / 309QuickBurro 从入门到精通 - 中间件服务端高级编程所有© 樵夫软件开发服务程序 API 函数库单元(老版本,将逐步废弃)服务程序 API 函数库单元(新版,推荐使用)NodeServiceAPI.pasQBServiceAPI.pas AlidayuAPI.pas AlipayAPI.pas BaiduTTSAPI.pas FiredacEngineAPI.pas LazPluginApi.pas MBPluginApi.pas UnidacEngineAPI.pas WeixinApi.pas WeixinEntApi

49、.pas WxPayApi.pas阿里大于接口 API 函数库单元支付宝支付接口 API 函数库单元语音接口 API 函数库单元FireDAC 数据库引擎 API 函数库单元Lazarus 服务插件接口辅助函数单元移动服务插件接口辅助函数单元UniDAC 数据库引擎 API 函数库单元订阅号/服务号接口 API 函数库单元企业号接口 API 函数库单元支付接口 API 函数库单元对以上这些API 库函数单元中的 API 函数的功能、用法,将在本资料的最后一章中进行详细介绍,本节只做概括性的梳理,目的是概况全篇,以便更好地深入各章节。1.9、插件间共享数据的方法插件模块除了需要和宿主服务程序及客

50、户端应用程序之间交换数据、与底层的数据库及操作系统间交换信息外,有时还需要进行不同插件之间的信息共享交换、插件的不同调用时期间的信息共享交换等,比如,插件需要向数据处理插件传递所到的数据,等等。出于这种需求,QuickBurro 中间件系统中实现了一种称之为“数据栈”的技术,以“驿站”(公用数据区)的形式向“各位旅客”(插件)提供数据寄存、删除等功能。数据栈分为公用数据栈和私有数据栈两类,“私有数据栈”是归属于某插件的局部的数据区,一般只由本插件在不同的调用时段进行读写;而“公用数据栈”在这里是指一种用于 删除失效了的数据等等,是 QuickBurro的公用数据区,可以向其中“寄存”数据、检索

51、数据、从中为了实现服务端程序的各个部分(特别是插件之间)进行数据共享交换的一种数据结构及技术。对于数据栈的使用,我们专门在服务 API 函数库单元 qbserviceapi.pas 中封装了一个 TAPIDataShare接口类,供应用程序员在编写服务端插件时调用数据栈请参考本资料的“8.8、数据共享交换接口 API”一节。的 API 函数。关于此接口类的详细功能和用法,1.10、插件的安全性服务端插件编写完成、并将.dll 部署到服务端之后,有多种方法可以这些插件的安全性:安全性验证通过的调用、安全性验证失败的调用。1)、插件对于 C/S 三层服务插件,可以在插件时指定其,然后在对它的 RP

52、C 调用需要指定此调用插件。中间件在收到 RPC 调用请求时,会检查的正确性,如发现不对,就会拒绝2)、特殊的调用参数插件可以要求调用方传入特殊的标记才认为是合法的调用,这也是一种很常见的确保调用安全的措施,插件导出函数处检查传入的参数包里若不包含调用标记,则拒绝继续执行,直接返回执行失败。12 / 309QuickBurro 从入门到精通 - 中间件服务端高级编程所有© 樵夫软件开发3)、应用业务权限验证可以将应用程序相关的安全验证信息包含在调用参数里传到插件,插件在处理业务逻辑时先判定安全验证信息是否,是,继续处理,否则拒绝继续执行。二、C/S 三层服务插件开发2.1、C/S 三

53、层服务插件的接口规范这是一类 QuickBurro 中间件中最早实现的服务端插件类别,功能强大、细节完善、使用广泛,主要为VCL 三层架构应用开发提供公用功能服务和应用相关的业务逻辑处理服务,其接口规范如下:模块类别:标准 Windows 动态库(.DLL)开发工具:Delphi 6 起到最新版 Delphi,都支持插件用途:VCL 三层架构客户端程序功能服务、服务端计划任务、或消息触发服务命名规则:普通文件名,建议文件名长度<64 字符,全路径长度<=96 字符内存管理:FastMM4(插件工程 Uses 的第一个单元线程模式:多线程及单线程均支持,取决于插件的驻留模式:即时加载

54、不驻留、驻留内存、用户程序Fastmm4) 方式驻留三种方式任选安全:验证及插件内调用标志验证等方式:需要接口标准:Stdcall(参数从右至左入栈,Pascal 标准) 调用方式:同步调用、异步调用都支持调用标识:插件时指定的插件标识代码导出函数:RemoteProcess(主函数)、ApiInitialize(初始化)、ApiUninitialize(善后) 部署方式:静态部署+运行时动态部署,支持热插拔调用方法:TDllPlugin 控件的 BinaryRPC 方法及 AsyncRPC 方法、模块触发器调用、计划任务调用以及动态调用DLL 方式接口参数:TQBParcel 容器对象之一传

55、入参数、另一 TQBParcel 容器对象传出参数,参数个数不固定,应用程序员自行约定API 函数:可调用 VCLSDK 下提供的全部 API 函数库单元延迟卸载:非驻留模式自动支持延迟卸载共享数据:私有数据栈、公用数据栈对于 C/S 三层服务插件,中间件服务程序除了将客户端调用提交的参数通过TQBParcel 对象传递给插件外,还会将中间件的一些重要系统参数、API 函数基地址等信息一并随参数包传递到插件,插件编,除了从参数取普通请求参数外,还可以取用这些系统信息:API 函数基地址: 通信密钥:被调插件文件名:本节点代码:InParcel.PutQBIntegerGoods('Callback_Proc_List',QBInteger(NodeService.ExportAddrList0);InParcel.PutAnsiStringGoods('Transfer_Key',NodeService. TransferKey); InParcel.PutAnsiStringGoods('Dll_Filename',ansistring(NodeService.Pluginsj.PluginFilename); I

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论