Skip to content

最好的 app logic 容器,oracle database; The best app logic container oracle database.

kaven276 edited this page Jun 30, 2015 · 1 revision

在信息系统的架构从两层结构向三层结构转型的过程中, 应用逻辑从客户端程序中向位于服务器端的中间层转移。 从一开始,基于c语言的处理逻辑在tuxedo容器环境中执行; 到后来,基于java语言的处理逻辑在J2EE容器环境中执行。 这些容器提供了各种技术层面的基础服务, 包括:

  • 和客户端的网络连接通讯
  • 请求和相应地解析和序列化
  • 进程池线程池等并发服务管理
  • 数据库连接池管理
  • 坑爹的 OR-Mapping

但是,从一开始,就有很多信息系统将和界面无关的后台业务处理逻辑数据处理逻辑都写到数据库的存储过程中。 这种做法从“客户端/数据库”两层架构开始,到“客户端/应用服务器/数据库”时代, 一直就有这么做的,由于业务逻辑写到的数据库存储过程中,更容易集中管理维护,也更容易被各种外围程序调用。 当然,还有更多地好处,后面都会介绍。

如果数据库的存储过程环境足够强大,能够将业务逻辑放到数据库存储过程来实现(实际上ORACLE已经做到了), 那么数据库,或者说 ORACLE instance 就是 PL/SQL 存储过程的容器, 那么这个 app 容器和流行的 Tuxedo(c)/J2EE(java) app 容器比,能看到什么呢? (当然,很少见到有人把 database 当做 app 容器,而是仅仅把 database 当做数据存储的仓库来用)

更高的稳定性

oracle 存储过程在 oracle instance 环境中执行,其稳定性从常年在各个使用 oracle 的信息系统项目中广泛使用得到了充分证明。

LRU 共享内存来管理代码空间

从技术角度分析,PL/SQL 存储过程被编译为p-code后保存在 shared pool 中,采用 LRU 算法来解决内存不足的问题,不会因为一些不被使用的存储过程而实际占用有限的内存空间。

没有什么要命的最大内存限制

对于J2EE来说,由于单个JVM虚拟机的最大内存限制,如果你的机器的内存太多的话,只能通过多运行几个实例来提供机器的利用率了,例如跑Tomcat,你可以多装几个Tomcat并做集群。 而采用 oracle 存储过程后,ORACLE 能够利用的内存基本上只收到服务器物理内存大小的限制,因此PL/SQL存储过程可以利用的内容容量几乎没有什么限制。

抗异常的多进程加共享内存模式

另外,存储过程执行异常永远也不会造成进程崩溃;同时,每个 oracle server process 执行自己的存储过程,单个进程的问题只会影响该进程,不会引发其他进程的问题。而一个 J2EE 容器是单进程的,可能因为一个线程出现的问题,可能造成整个服务崩溃。

抗内存泄露

  • PL/SQL 存储过程不使用其他语言的堆变量堆空间,也就没有什么机会造成内存泄露
  • PL/SQL 存储过程中调用 SQL 等使用的各种内存空间,都位于 PGA 内存,并且可以在执行下一个 SQL 中重复利用
  • 对一些占用 SGA 共享内存的空间,由于 SGA 各个内存区都采用 LRU 算法管理,不用到的内存都会被重新利用从而是内存占用得到释放
  • 采用 Noradle 架构,可以控制每个服务进程执行多少请求后或者生存多长时间后,自动退出并由noradle来重新启动。从而可以完全释放PGA内存。

oracle 支持各个内存区域大小的动态调整

如果发现 shared pool 或其他内存空间的命中率下降,或者发现 PGA 空间紧张,都可以在数据库运行期间,动态的调整各个内存区域的大小,来根据应用的实际特点进行适应性调整。这个在J2EE中不存在支持。

抗 ORA-600 ORA-7445 等内部错误

如果采用 J2EE 连接池来访问 oracle 数据库,当一个数据库服务进程遭遇过 ORA-600 或者ORA-7445 异常后,往往发往该服务进程的后续请求还会再碰到上述异常。但是如果关闭该进程,将新请求发往别的进程或者新进程有都正常,这个可以称之为进程对引发内部错误的积累保持作用。采用Noradle架构,只要服务进程发现 ORA-600/ORA-7445 内部错误,该进程就会主动关闭,等待系统重启新的对位进程,从而避开这个问题。

对开发更加方便简洁,对运行的负担更小

一套数据类型

没有 c/java 数据类型到 oracle table 数据类型的匹配转换的麻烦事,也不会因为数据类型匹配造成长度精度,null处理等容易造成问题的烦恼。因为 PL/SQL 可以直接利用 oracle table column 的字段类型,这种统一的数据类型使得开发更简单,也完全避免了数据类型方面的异常。

无需重复的变量定义

使用 table.column%type table%rowtype 等方式定义存储过程中的变量类型, 不想多层架构应用,需要以数据库模型为标准,定义一套甚至多套本质上是一回事的数据结构。 那样在数据库结构做变更的时候,需要同时变更每套映射的应用层数据结构,非常麻烦,也容易出错。 而使用 PL/SQL 存储过程,开发者几乎不用在费心去定义什么所谓应用层的数据结构(仅仅为了映射数据库表结构)

没有网络传递和网络数据处理

PL/SQL 存储过程在 oracle server process 中执行,直接访问 oracle instance SGA 共享内存,没有网络开销,没有数据的序列化和解序列化的开销

和 SQL 集成更好

for loop / static cursor / dynamic cursor 的使用都可以方便的将SQL集成到 pl/sql 中, PL/SQL 中的变量可以直接绑定的SQL中, 天然的SQL参数绑定静默的解决了传统应用中普遍存在的拼SQL造成的share pool破坏。

使用 noradle 后,开发更省心,专注业务逻辑即可

不用管理并发

noradle dispatcher 根据配置和动态负载,控制每一个noradle客户端的最大并发量。 Noradle系统管理员根据硬件配置决定启用的服务进程数, dispatcher接入管理器平衡各个客户端的并发需求, 将全部可用的进程合理的分配和各个客户端。 而传统的架构,是由客户端控制并发度,存在以下常见问题:

  • 不能充分利用服务器进程数资源
  • 超过服务器硬件负载设置太大的并发度反而造成系统变慢
  • 不能协调好各个客户端的处理需求
  • 一些客户端占用过多资源不充分利用,另外一些客户端却因为分配的资源太少而不能满足处理需求

不用管理数据库连接池

采用 noracle 后,应用处理的核心在数据库内部,当然就不用连接数据库了。 而各个 noradle 客户端连接到 noradle dispatcher 时, 只建立一个到 dispatcher 的 stream 连接(通常是普通的TCP connection), 具体对数据库的并发访问又服务端的 dispatcher 控制, 并由客户端遵照执行。 客户端代码无需处理并发使用的多连接,也无需配置并发度。 client-to-dispatcher 的单链接采用多路复用传输所有并发请求和相应地frame, 同时还传输 control frame。

总结

可以看出,采用 noradle 存储过程架构开发应用逻辑, 信息系统将更稳定、更健壮;开发和运行的开销更小,成本更低。

Clone this wiki locally