发明内容
本发明涉及对参与两阶段提交的资源进行动态重定序以启发式地进行最后代理优化的方法,***和存储介质。
第一方面用于最后代理优化的方法,包括:为应用程序建立到多个资源中的每个资源的连接;
确定当前事务上下文;
收集与每个资源相关的使用统计数据;及
根据所述收集到的与每个资源相关的使用统计数据,确定当前事务上下文中每个资源的顺序以实现基于使用统计数据的最后代理优化;
其中在确定当前事务上下文中每个资源的顺序时,将只读资源排在前面。另一个方面是提供一种用于最后代理优化的准备***,包括:
用于保存多个资源中的每个资源的使用统计数据和历史信息的直方图的存储设备;及
事务管理器,用于基于直方图对当前事务中的每个资源进行定序,使得只读可能性大的资源被首先准备,并且无需准备非只读资源。
另一个方面是用于最后代理优化的另一个***,,包括:
在通用计算机上运行应用的服务器;
驻留在服务器上的应用程序容器;
在应用程序容器中运行的至少一个应用程序,应用程序包含使用多个资源的至少一个事务;
服务器上的事务管理器,用于在两阶段提交过程的提交阶段期间,根据所述多个资源中的每个资源的使用统计数据和历史信息对资源进行定序以实现最后代理优化;及
服务器上的连接管理器,用于提供资源给应用程序并且用于使用事务管理器编入资源。
另一个方面是存储用于执行最后代理优化方法的指令的存储介质,其中使用统计数据被存储在直方图中。使用直方图对当前事务上下文中的资源进行定序以实现最后代理优化。自主调整定序以在使用方面产生变化。
具体实施方式
图1示出两阶段提交过程的现有技术例子,其中没有为最优提交而对资源进行定序。在第一和第二步骤中,来自应用程序容器和应用程序管理器的提交流向事务。在事务中存在两个资源。在第三步骤中,第一资源接收准备调用,并且向事务返回认可。在第四步骤中,第二资源接收准备调用,并且向事务返回只读。这结束了两阶段提交的第一阶段。由于资源中的一个返回认可,所以在第五步骤中结果被记录,并且在第六步骤中,提交在该资源(第一资源)上流过,对此第一资源返回认可。这结束了两阶段提交的第二阶段。
在这个例子中,通常需要两阶段提交的选择事务被缩减为一阶段提交。当请求准备时,资源在其对后续提交或回退调用没有要完成的更新的情况下,返回只读值。如果在事务中编入n个资源,并且前n-1个资源对准备调用表决为只读,则剩余资源变成编入的唯一资源,并且执行一阶段提交。这是最后代理优化,因为最后资源(或代理)能够执行一阶段提交优化。在这种情况下,提交事务所需的网络调用的总数减少到n,并且在准备阶段之后不必记录。
如果最后资源之前的所有资源表决为只读,则可以执行最后代理优化。例如,假定事务编入n个资源,其中n>1。如果第一个资源对准备调用表决认可,并且剩余n-1个资源表决只读,则仅留下一个编入事务中的资源。然而,这个资源已经为准备而驱动。由于两阶段提交中的阶段一已经执行,所以不能执行一阶段提交。随着两阶段提交的第二阶段,结果被记录,并且驱动剩余资源进行提交。在这种情况下,由于一个资源被准备以及提交,所以存在总共n+l个提交事务所需的网络调用。
在这个示例性实施例中,如果资源被最优定序,则额外网络调用和日志写入在上述情景中是可避免的。如果不能表决只读的资源被最后驱动,则在使用最后代理优化时不需要额外网络调用和日志写入。
图2示出了优化的最后代理提交过程的示例性实施例。图1所示的相同事务在图2中示出。然而,在图2中,资源被定序,使得在第一阶段期间,第二资源被首先驱动。在第三步骤中,响应准备调用,第二资源返回只读。由于只有一个资源,即第一资源留下,在第四步骤中,它被驱动提交,而无需执行阶段一的剩余部分。
事务处理的例子是储蓄帐户和支票帐户之间资金的转移。在存在***故障的情况下,两阶段提交操作可以被用于进行恢复。假定存在从储蓄帐户传送$100到支票帐户的请求。为了满足请求,$100必须从储蓄帐户中扣除。如果从储蓄帐户中扣除$100,但是在$100记入到支票帐户之前***失败,则存在问题。两阶段提交操作包含向资源(例如储蓄帐户管理器和支票帐户管理器)通知需要从储蓄帐户转移$100到支票帐户,并且在存储用于可能的恢复的事务记录的同时请求其它资源的批准。一旦存在批准并且所有方面均没有问题,则事务被提交并且资源有责任完成事务,即使存在***失败(在这种情况下,所存储的记录在***重新启动之后被用于完成事务)。
当事务中只有一个更新方或一个资源留下时,可以执行最后代理优化。不需要请求唯一一个资源进行提交。假定事务是储蓄帐户的余额查询;即一个资源(储蓄帐户管理器)的只读事务。当询问储蓄帐户管理器是否能够提交时,它响应以忘记(forget)。
示例性实施例自动确定顺序,使得在指定上下文中可能表决认可的任何资源之前轮询在指定上下文中可能表决忘记的任何资源。首先确定所有只读动作,把提交者留到最后。最优的情况是仅留有一个提交者。基于可以显示在直方图中的使用数据进行关于资源是否可能表决忘记或提交的预测。
图3示出事务***的示例性实施例。应用服务器300包含应用程序容器302,连接管理器304及事务管理器306。例如应用服务器300的应用服务器是任何通用计算机。
应用程序容器302拥有第一应用程序308和第二应用程序310。例如应用程序容器302的应用程序容器是用户能够部署要运行的应用程序的地方。应用程序容器是受管理的环境,其中应用程序具有对它可用的某些服务,例如连接管理和事务管理。根据怎样定义受管理的环境,应用程序能够具有变化的粒度,例如部件级别。在这个例子中,第一应用程序308是独立应用程序,同时第二应用程序310包含第一模块312和第二模块314。
连接管理器304包含第一资源(A)316和第二资源(B)318。
事务管理器306从各个资源收集表决,并且确定结果。事务管理器306负责对资源进行定序,其对应用程序308,310透明。用于对参与两阶段提交的资源进行动态重定序以启发式地进行最后代理优化的示例性实施例驻留在事务管理器306中。在这个示例性实施例中,使用散列映射将使用统计数据存储在事务管理器306中。在其它示例性实施例中,使用统计数据被存储在事务管理器306可访问的任何存储设备中。
假定第一资源316是储蓄帐户,并且第二资源318是支票帐户。并且,假定第二应用程序310中的第一模块312对储蓄帐户执行余额查询,即只读操作,并且第二模块314对支票帐户执行提取(withdrawal),即修改该资源。在这种情况下,期望基于使用统计数据对资源316,318进行定序,使得只读事务(余额查询)首先进行,并且修改事务(提取)最后进行。
为了使事务管理器306使用最后代理优化对资源进行定序,事务管理器306需要先验地知道资源在它们被驱动进行准备时将怎样表决。在某些***中,***管理员可以提供部署提示给事务管理器以指示特定资源将怎样作为。这允许事务管理器306将可能表决只读的资源定序在从不表决只读的那些资源之前。然而,这需要***管理员可得到这个信息,并且需要使用这个资源的所有应用程序以类似方式使用它,因为多个应用程序可能以不同方式使用相同资源,因而需要相同资源的多个配置。由于工作负载模式可表现出随时间变化特性,即使在***的配置没有改变时也是如此,因此对于某些安装,这是不切实际的。
图4示出了用将资源编入当前事务的处理的示例性实施例。在第一步骤中,应用程序容器302内的第一应用程序308正调用连接管理器304以建立到一资源,例如保存银行帐户的关系数据库的连接。在第二步骤中,连接管理器304调用应用程序容器312以检索应用程序标识符(ID)。应用程序标识符是在应用程序容器302内为第一应用程序308部署的标识符。作为响应,应用程序容器312返回ID=1。在步骤三,连接管理器304通过事务管理器306进行检查以确定第一应用程序308是否具有事务上下文。它有,所以在步骤四连接管理器304编入第一资源(A)316。在步骤五,当前事务通过事务管理器306进行检查以得到到目前为止针对第一资源(A)316产生的使用统计数据,并且返回到连接管理器304。
在这个例子中,″A1″是应用程序名称(应用程序″1″)和资源名称(资源″A″)的组合。其它示例性实施例可以使用任何其他唯一标识符。在图3中,第二应用程序310具有两个部件,第一模块312和第二模块314。为了跟踪特定应用程序和特定资源的正确使用统计数据,指示第二应用程序310正使用第一资源316是不够的。而是,事务管理器306通过容器管理器304进行检查以确定哪个部件正在运行。在这种情况下,它是第一应用程序308。接着,当连接管理器304正编入第一资源316时,连接管理器304向事务传递应用程序ID″1″和资源ID″A″。事务连接它们以产生″A1″,以便确定正确部件的使用统计数据。部件的粒度取决于维护ID列表和目前运行的应用程序的ID的应用程序容器302。例如,在Java2平台中,企业版(J2EE)服务器,应用程序被分解成模块,并且模块被分解成部件,即3个粒度级别。在其它示例性实施例中,可以有或多或少的粒度级别。
图5图解了示例性实施例如何针对多个应用程序跟踪资源的使用统计数据。对于第一资源(A)316,存在3个部件的使用统计数据,即第一应用程序308(ID=A1),第二应用程序310的第一模块312(ID=A2.1)和第二应用程序310的第二模块314(ID=A2.2)。
所有这些部件500,502,504的资源统计数据均包含准备,只读和失败的计数,以及只读(RO)和失败的等级。只读等级=准备数量/只读数量。只读等级1是最高可能等级,指示每次只读的表决。失败等级=准备数量/失败数量,其中失败指示远程资源管理器在准备期间遇到例如处理XA异常(XAException)的某种异常条件。这里,由于它与ID-A1的准备数量(准备=100)相同,所以失败等级100是ID=A1的最高可能等级。
图6示出了优化准备处理的资源排序的示例性实施例。这个示例性实施例包含确定怎样排序编入事务中的资源,使得结果排序产生如上所述的最后代理优化。该方法无需***管理员的干预动态对资源进行定序。
在这个示例性实施例中,为了预测资源的将来行为,在直方图中跟踪每个资源的以往行为。直方图是存储器中存储的表格,使用情况的表格和历史记录。当情况出现时,搜索表格以查看它是否在以前出现过。直方图记录针对指定***和情况资源表决只读或无法完成准备阶段的频度。事务管理器使用这个信息预测在当前事务中资源可能怎样作为,并且对资源进行定序,使得可能表决只读的那些资源被首先驱动。这增加了能够执行最后代理优化的频率。
在这个示例性实施例中,直方图包含资源实例到使用统计数据的映射。在使用统计数据中,若干计数器被维护。一个计数器表示这个资源已经准备过的总次数。另一个计数器表示这个资源已被表决只读的总次数。另一个计数器表示这个资源在准备阶段内出现异常的总次数。使用这些计数器,资源实例按照相对于准备总数的表决只读频度和相对于准备总数无法完成准备频度进行排序。
在另一个示例性实施例中,应用服务器在通用计算机上运行。应用服务器包含容器,连接管理器和事务管理器。在容器内,部署和运行一或多个应用程序。连接管理器负责向容器中运行的应用程序提供资源实例,并且通过事务管理器编入那些资源。事务管理器负责产生容器中运行的应用程序的事务边界,提供编入事务边界的资源的原子结果,并且在提交阶段对资源进行定序。
在这个示例性实施例中,当部署应用程序时,它被分配应用ID。根据怎样构造应用程序,这个应用ID被进一步分解成应用程序内的部件。应用程序内的每个部件也基于应用程序的总体ID被分配ID。应用程序内的每个部件提供描述部件事务语义的部署元数据。元数据描述部件是否应当在事务内运行,及部件是否应当加入可能在其进入时已经运行的事务。
在这个示例性实施例中,当应用程序被驱动时,容器***件的元数据并且把这个请求所需的事务上下文通知事务管理器。接着执行应用程序代码。当应用程序需要使用资源(例如,一部分关系数据库)时,应用程序通过连接管理器请求连接。连接管理器检查当前事务上下文,并且在存在事务的情况下,连接管理器向事务管理器传递资源和当前执行的部件的ID。事务管理器接收资源实例并且把它转换成标识符,该标识符与部件的ID连接以产生表示资源和使用资源的部件的标识符。
在这个示例性实施例中,存在实现为把标识符映射到一组使用统计数据的散列映射的直方图。通过把部件ID和资源ID连接在一起,我们具有每个资源的多组使用统计数据,使用资源的每个部件有一组。使用统计数据与资源实例结合,并且共同被编入当前事务。接着,连接管理器把到资源的连接返回到应用程序代码。
在这个示例性实施例中,使用统计数据包含通过将准备总数除以只读表决总数而产生的只读等级。每次100%表决只读的资源具有等级值1,其是用于优化的最优可能等级。每次0%表决只读表决只读的资源具有等于它已经准备的总次数的等级。通过将准备总数除以失败或异常总数来确定失败等级。具有高等级的资源被排序在具有低等级的资源之前。每次100%失败的资源具有等级1。
在某些实施例中,所有计数器被初始化成1以防止在计算等级时除以0。在某些实施例中,当进行变化以允许配置改变快速反映在使用统计数据中,或反映在任何其他适当时间安排上时,在指定时间间隔复位计数器和等级。在某些实施例中,如果准备计数器达到***的最大值,则等级和计数器被复位。
在某些实施例中,等级仅在指定间隔被计算。在某些实施例中,对于前100个准备,每次准备总数递增时计算等级。对于接着的100个准备,每十次准备总数递增时计算等级。对于接着的10,000个准备,每100次准备递增时计算等级。对于所有剩余的准备,在某些实施例中,每1000次准备递增时计算等级。
在这个示例性实施例中,将使用统计数据封装成对象,并将该对象***到排序列表中。排序列表接收两个比较器对象中的一个。比较器对象基于只读等级或失败等级排序使用统计数据。
在这个示例性实施例中,当部件结束执行时,容器再次***件的元数据以确定当前事务上下文是否已经结束。如果事务上下文结束,则容器联系事务管理器以完成事务。事务管理器基于相关的使用统计数据对象排序编入事务中的资源。只读比较器把具有低只读等级的资源放置在列表的开始处。
在这个示例性实施例中,事务管理器基于其等级驱动每个资源的准备。当准备被驱动时,资源的准备计数器递增。当资源表决只读时,该资源的只读计数器递增,并且该资源被从编入事务中的资源的列表中清除。在所有表决之后,如果单个资源保持编入,则执行最后代理优化以结束事务。如果响应准备调用,资源表决认可,则列表的比较器切换到失败比较器,按照其失败等级排序剩余元素,使得可能失败的资源被首先驱动。如果资源失败,则由于结果现在为回退,所以不需要在剩余资源上驱动准备。在那些不大可能失败的资源之前排序可能失败的资源在实际失败情况下额外节省了流过网络的若干准备,然而这应当只在唯一代理优化不再可能时进行。两阶段提交接着继续对剩余资源进行。如果资源失败,则其失败计数递增,并且由于资源将被回退,所以跳过剩余资源的准备阶段。
如上所述,本发明的实施例可以实现这些处理的计算机实现的处理和设备的形式体现。本发明的实施例也可以包含以例如软盘,CD-ROM,硬盘驱动器或任何其他计算机可读存储介质的有形介质体现的指令的计算机程序代码的形式体现,其中,当计算机程序代码被载入并且通过计算机执行时,计算机变成实践本发明的设备。本发明也可以计算机程序代码的形式体现,例如在存储介质中存储,载入和/或通过计算机执行,或通过例如电连线或电缆,光纤,或电磁辐射的某种传输介质发送的计算机程序代码,其中当计算机程序代码被载入并且通过计算机执行时,计算机变成实践本发明的设备。当在通用微处理器上实现时,计算机程序代码段配置微处理器以产生特定逻辑电路。
虽然参照示例性实施例描述了本发明,然而本领域的技术人员将理解,在不偏离本发明的范围的情况下可以进行各种变化并且可以用等同特征代替其中的要素。另外,本发明的各种实施例的较小调整可以使用对标准的将来改进或变化。此外,各种部件可以硬件,软件或固件或其任何组合实现。最终,可进行许多修改以使特定情况或材料适合本发明的教导,而无需偏离其实质范围。因此,本发明不限于公开为本发明具体实施方式的特定实施例,本发明将包含属于所附权利要求书的范围的所有实施例。此外,术语第一,第二等等的使用不表示任何顺序或重要性,而是术语第一,第二等等被用于把一个要素与另一个要素区分开。此外,术语一,一个等等的使用不表示数量的限定,而是表示至少一个所指项目的存在。