DataSnap

看到网友的观点,切下来做个记号,最近研习

我补充一点点:

我买过李维的所有的书。通过李维的书入门多层架构后,也在几个比较大的项目上实际运用过。谈谈我的实际经验。

1. COM Based 的架构:其实这种架构,如果采用 COM ,效率是非常高的。一套系统,后端 SQL SERVER 只需要10个连接,前面顶200个 UI 前端,一点问题都没有。
2. 我自己后来通过学习李维关于 WebService 的书,后来做的东西都转为采用 WebService 了,对 WebService 还算熟悉。目前暂时还没时间实际去适应 REST 架构,所以对新的 REST DataSnap 不熟悉。

要做多层架构的东西,最重要的,是一定要去掉以前做2层或者单层架构时,在 UI 客户端直接连数据库的使用习惯。这个使用习惯背后,其实就是【状态】。

Delphi 做多层架构,就是在客户端使用 ClientDataSet。传统的 COM Based 下,默认给出的使用方式,和两层非常类似,也是有状态的。这样,不熟悉三层架构但熟悉两层的人,非常容易上手,而且拖拉几个元件,也就可以做出一个简单的程式来。但是,这样并不是真正理解了三层架构。

真正要理解三层架构,一定要做到【无状态】(Staeless)。理解了【无状态】,也就不存在翻页的问题了 --- 翻页,应该是数据库 SQL 要解决的问题。

如果你做过网页,不管是 ASP, ASP.NET 还是 PHP 还是 WebBroker,你应该就知道,网页和后端服务器是脱离开的。一次访问,网页打开后,你的页面(Web Browser)就已经断开和 Web Server 的 TCP 连接了。如果这时候你需要下一页数据,点了【下一页】,前端网页(HTML, JavaScript)会将当前页的相关参数(一般是该页里面最大的数据的主键值)传递给 WebServer, Web Server 端的 ASP/ASP.NET/PHP 等等,根据这个值,通过 SQL 语句向 DataBase Server 要下一页的数据。

上述过程,就是一个无状态的过程。所谓无状态,是指服务器端没有保存客户端的状态,服务器端根本不知道客户端的【下一页】是从哪条数据开始的。客户端需要下一页,必须告诉服务器端自己当前要从哪条数据开始。至于【一页】包含多少条数据,也可以由客户端告诉服务器端,你也可以 hard code 硬编码写死在服务器端的代码里面。

在 Delphi DataSnap 底下,一样必须要这样做,这个三层才有三层存在的意义。最大的好处就是:客户端从服务器端拉完数据,就断开了和服务器端的连接(如何断开连接的?等一下说。),这样,服务器端就可以服务器其它客户端的连接请求。这样,才可以一台服务器,10个数据库连接 license 就能支持200个以上的客户端的访问。这样做更大的好处是,当那台服务器顶不住更多客户端的访问的时候,你加一台跑中间层的服务器就好了。对于客户端来说,因为是无状态的,它可以上一次从 A 服务器拉数据,下一次把数据提交给B服务器,哪个不忙就找哪个(这就是传说中的负载均衡)。

至于使用 DataSnap 要做到无状态,你必须得自己多写点代码,而不是拖拉几个元件就完成。

对于前端UI程式的数据需要提交到 DataBase Server 来说,也一样:提交的时候,前端(或者叫客户端)连接中间层(或者叫服务器端),将数据提交过去,中间层负责把数据真正提交给 DataBase Server,中间层的代码是你自己写的,你可以在这里,写一些权限控制等业务逻辑代码,决定是否允许提交等等业务逻辑。

这里讲的这些概念,本质上是由 Midas.dll 提供的一个功能来实现的:服务器端通过 DataSetProvider 将来自 DataBase Server 的数据打成一个包,然后通过网路通信协议(比如 TCP)丢给客户端;客户端将这个封包,丢给 ClientDataSet,你就可以通过绑定到 ClientDataSet 的 DBGrid 看到数据了。如果你在 DBGrid 里面编辑了数据,需要提交,则客户端向服务器端发起建立一个网路连接,然后将需要提交的数据打成一个包(我们甚至可以看到这个包是一个 OleVariant 格式的 Data),通过网路通信,丢给服务器端的 DataSetProvider,然后在服务器端,DataSetProvider 会将这个数据,变成 SQL 语句的 Update xxx 语句,实际去更改 DataBase Server 里面的 Data。这个过程完成后,客户端断开和服务器端的网路通信。这样就可以做到无状态,也可以做到服务器端只有10个实例在运行但可以同时服务200个客户端。

概念如此,但具体的技术实现上有一点不一样。简单说,如果用 COM Based,那么,你在客户端的 COMConnection 一旦 Connected = True 就是建立了和服务器端的网路通信连接。如果你不断开它,它就一直占用着。这时候服务器端就必须有一个 COM 或者 COM 的实例运行起来去服务器它。而这个 COM 的实例,可能会建立一个和 DataBase Server 的连接。如果你的前端程式一启动,就打开 COMConnection 的连接,一直到程式关闭,才关闭连接,那就不是前面说的无状态,关于3层的好处,也就享受不到。

如果是 WebService,基于 WEB 的原理,你每次访问,就是建立一个和 WEB SERVER 的 TCP 连接,访问结束,这个连接也就断开了。它天然是无状态的。你必须要自己写一些额外的代码来实现自己的需求,比如翻页(无状态模式下,千万不要写 select * from MyTable 这样的代码。有状态模式下,这样的代码没问题,数据库服务器也就是 DataBase Server 里面会有游标,它一次可能只丢出100条数据给你,你向下滚动的时候,它才继续丢数据给你,它在服务器端帮你维护了状态。无状态下,它会把里面的几十万条数据一次都丢给你,然后网路很慢,你就等死在那里了。)。


在 Web Service 模式下,一开始我按照李维的讲法,把 WebService 只当作一个薄中间层,它去向真正的中间层 COM 那一层取数据,由 COM 那一层去真正连接数据库。后来发现,让 WebService 直接连接数据库,在一些不是非常大的系统上面,也是可以的,问题不大。

WebService 底下,如果在服务器端直接嵌入 Indy THTTPServer,把服务器端直接做成一个普通的 EXE,它自己就包含了一个 WebServer,这样的方式,调试的时候非常方便。到 XE3 的时候, Indy 已经比较稳定,我对 TIdTCPServer 做过压力测试,发现并发2000个连接不停地连上,取数据,断开,这样连续跑几个小时,都没问题。因此,现在简单的应用,我都直接采用内嵌 IdHTTPServer 的方式。当然,对于复杂的应用,我会分两步:
第一步,将服务器端编译成 CGI 的方式给 IIS 调用。这样就算服务器端有 BUG 会导致内存泄漏或者出现AV错误等等,它不会将 IIS 搞死。一次访问失败后,不影响下次。
第二步,如果确认自己写的服务器端没问题,又想提高 Web Server 的效率,就把它编译成 ISAPI。不过 ISAPI 一但出问题,会把 IIS 搞死的。

OK,到这里,我自己的使用经验差不多了。

对于最新的 REST DATASANP,李维的书我也买了,还没时间仔细学习。不过我知道它和以前的架构的区别主要是:
1. 传输的数据封包,采用 JSON。在 Com Based 方式下,数据封包是 OleVariant,是符合 COM 协议的二进制包;在 WebService 底下,是 OleVariant 但这个 OleVariant 在网路上被编码成 XML。我觉得封包格式的区别,对于写CODE的人来说,关系不大。
2. COM 和 WebService 都是基于 Interface 编程的。这种模式非常好。而 REST DataSnap 变成了基于 Class/Object 的,我反倒觉得不太好。
3. REST DataSnap 主要是基于 IdTCPServer 的。这样,客户端和服务器端可以保持长连接,好处是服务器端可以回叫(CallBack)客户端,坏处是【无状态】这种编程模式,反倒可能就让初学者不容易掌握了。因为一旦保持客户端和服务器端的连接,则非常容易写成有状态方式。当然,有状态的方式,代码会少写很多。

以上三点,不一定对,因为我还没真正深入去使用 REST DataSnap。


DBExpress 只是一个 DataBase 存取的架构,和 BDE 类似。所以,它和【三层】没有关系。

但它又是专门为三层而生的,无状态的三层。它和 BDE / ADO 不同的地方在于,它是【单向游标】。也就是它作为 DataBase 的存取,它一次性把获取的 Data 都丢出来,不负责维护缓存和游标。因此,你对 DBExpress 的 TSQLDataSet 不能做 Prior 这样游标向前滚动的操作,而BDE/ADO是可以的。

因此,如果你拿一个 DataSource 指向它,然后拿一个 DBGrid 绑定到这个 DataSource 上去,然后你想在 DBGird 里面前后滚动浏览 Data 是不行的。

但是,对于【无状态】的三层来说,服务器端从 DataBase 获取Data以后,把 Data 全部丢给客户端,客户端把 Data 都缓存在 ClientDataSet 里面,然后对 ClientDataSet 里面的 Data 来回滚动,过滤,查询等等操作,都没问题。操作完后,提交到服务器端。

DBExpress 这样做的好处是,服务器端的负担非常轻,因为它不用为每个客户端的连接维护一个 Data 的缓存和游标。这才是符合无状态的三层的意义。如果把三层搞成和二层一样,客户端的数据和游标,由服务器端来维护,代码倒是可以少写很多,但就享受不到三层的好处了。

--------------------------------------
不过,DBExpress 好像一直都有不少的 BUG。尤其是针对 FireBird 来说,有些 BUG 一直没改。现在 DELPHI 推出了 FireDAC 后,看起来是不打算修改 DBExpress 的 BUG 了,最好还是转去用 FireDAC 好了。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值