terracotta_具有Spring Web Flow和Terracotta的Spring Web应用程序

terracotta

抽象

Spring Web FlowSpring Framework Web应用程序堆栈的一个组件,它提供了一种编写有状态,会话式Web应用程序的简单方法。 通过允许您将Spring Web Flow定义为一个独立的模块,它可以独立于应用程序的其余部分进行配置和重用,从而使Web应用程序中的逻辑流成为一流的公民。

Spring Web Flow通过为状态数据引入各种范围为您提​​供了开发状态Web应用程序的新方法。 请求,快速,流畅和对话 。 它还提供了扩展点,用于自定义如何管理应用程序状态。

Terracotta for Spring是一个运行时,它通过跨多个JVM进行集群,为基于Spring的应用程序带来了高可用性。 无论范围如何,该产品都直接支持Spring Web Flows以及一般的Spring Bean )的透明和声明性集群。

在本文中,我们将首先为Spring提供Spring Web FlowTerracotta的概述,然后向您展示如何在编写有状态的,可对话的,可伸缩的和高度可用的Web应用程序时一起使用这些技术来进入一个新的维度。

什么是Spring Web Flow?

Spring Web FlowSpring Framework Web应用程序堆栈中的一个组件,它提供了一种编写有状态会话Web应用程序的简单方法。 通过允许您将Spring Web Flow定义为一个独立的模块,它可以独立于应用程序的其余部分进行配置和重用,从而使Web应用程序中的逻辑流成为一流的公民。 它与框架无关,可以轻松地与所选的Web应用程序框架一起使用,例如Spring MVC,Struts或JSF

使用专门为定义和组成页面流的任务而开发的领域特定语言(DSL)配置页面流。 当前的实现是XML和Java。

通过为状态应用程序数据引入各种范围,Spring Web Flow在开发有状态Web应用程序时为您提供了灵活性和功能。 适合不同用例和要求的请求,快速,流畅和对话。

以下是1.0发行版中最有趣的功能的简要概述(摘自InfoQ发行说明 ):

  • 在一个地方定义一个应用程序任务(例如搜索过程)的所有控制器逻辑,而不是在多个地方散布该逻辑。
  • 组合流可以从简单的零件创建丰富的控制器模块。
  • 使用自然的,面向对象的线性编程模型来执行严格的用户导航规则,而无需对冗长的if / else块进行编码。
  • 在流程执行期间分配的内存在流程结束或过期时会自动清除。
  • 使用您选择的基础Web框架在Servlet环境中部署执行流。
  • 更改基本的Web框架(例如Struts,Spring MVC,JSF等),而不必更改流定义。
  • 一起更改环境,例如从JUnit测试到Portlet,而不必更改流定义。
  • 在开发时动态地发展应用程序的导航规则,而无需重新启动容器。
  • 无需自定义编码即可自动获得正确的浏览器按钮支持(后退,前进,刷新)。
  • 将任务数据存储在四个托管范围中的任何一个中:请求,闪存,流和对话; 每个都有自己独特的语义。
  • 测试流无需容器即可隔离。 在部署之前,请确保您的应用程序控制逻辑有效。
  • 使用Spring IDE 2.0图形化地可视化和编辑您的流程导航逻辑。

听起来不错? 到目前为止,仅仅是概念和理论,但我们很快将研究所有这些在实践中如何实现。 因此,请继续关注。

企业中横向扩展和高可用性的需求

集群在企业应用程序开发世界中变得越来越重要。 开发人员不断需要解决以下问题:

  • 我们如何通过将应用程序扩展到单个节点之外来增强可伸缩性?
  • 我们如何保证高可用性,消除单点故障并确保满足客户的SLA(服务水平协议)?

可预测的容量和高可用性是生产中的应用程序必须展示出来以支持业务的操作特征。 一些公司要求其应用程序的正常运行时间高达99.9999%。 其他应用程序则没有,但所有应用程序都需要保持运行状态,直到SLA定义,并且以这种可预测的方式运行的应用程序在99.9%的水平上与在99.9999%的水平上一样困难。

从历史上看,集群是一个很难解决的问题。 在Spring Web Flow和一般的Web应用程序的上下文中,这尤其意味着以高性能和可靠的方式确保用户状态的高可用性和故障转移。 万一节点发生故障(应用程序服务器或JVM崩溃),使用粘性会话(这是配置负载均衡器的最常见和首选方式)是一个开始,但是我们还需要一种从一个用户迁移用户状态的有效方法。无缝连接到另一个节点。

说集群时,我们指的是什么?集群与缓存有何不同? 我们使用的集群的定义是:在多个JVM之间共享应用程序状态,而缓存可以定义为:使应用程序状态更接近其执行上下文。 从这个意义上说,缓存是集群的子集。

我们认为针对Web /企业应用程序的企业级集群解决方案应满足的最低要求是:

  • 可扩展性
  • 高可用性
  • 故障转移
  • 性能
  • 对现有代码的影响最小
  • 简单的部署和配置
  • 运行时可见性(监视)

现在让我们集中精力解决所有这些看似完全不同的需求。 解决问题总是有不止一种方法,并且市场上有许多产品声称可以为Web应用程序提供高可用性。 兵马俑提供了一种这样的解决方案。

什么是Spring兵马俑?

秦始皇为SpringSpring运行时为基础的,对于Spring应用程序影响最小的应用程序代码,并与部署和配置过程同样影响不大提供透明和高性能集群应用。 它通过在应用程序下面的堆级别上进行集群来实现此目的,而不是直接对应用程序进行集群。

与无状态应用程序相比,它允许开发人员开发单节点有状态 Spring应用程序。 这允许可伸缩的应用程序,而不必预先设计群集。 但是,当应用程序需要扩展应用程序或确保高可用性和故障转移时,他们只需在Terracotta配置文件中定义要在哪个应用程序上下文中集群的Spring bean。 然后, Terracotta for Spring确保应用程序被自动透明地集群化,并确保整个集群中的语义与单个节点上的语义相同。

Spring Web Flow的情况下,实际上甚至更简单。 为了使Web应用程序状态和延续存储库集群化,用户所需要做的就是在Terracotta配置文件中将特定的Web应用程序声明为已启用“会话支持”(请参阅​​下面的“声明性配置”部分)。 ',以获取详细信息)。

从高层次来看,Terracotta for Spring提供:

  • HTTP会话状态的集群 。 确保Spring Web Flow用户状态和继续存储库或HTTP会话中放入的任何其他状态的高可用性和故障转移。
  • Spring Bean成簇Spring Bean的生命周期语义和范围在整个集群中得以保留-在同一“逻辑” ApplicationContext中。 当前的可群集Bean类型是单例会话范围的 Bean。 用户可以声明性地配置要在哪个应用程序上下文中集群的bean。
  • 透明地对POJO进行集群 。 无需更改现有代码,甚至不需要源代码。 基于最小的声明性XML配置,在加载时对应用程序进行透明地检测。 Terracotta for Spring不需要任何类即可实现Serializable,Externalizable或任何其他接口。 这是可能的,因为它不使用序列化,而只是将实际的增量(已更改的数据)运送到当前需要它的节点(延迟)。
  • 虚拟内存管理 。 它还提供了分布式垃圾回收功能,并且还可以用作虚拟堆,例如,由于物理内存是按需分页的,因此它可以在具有4 G RAM的计算机上运行200 G堆的Web应用程序。 这意味着您不需要担心Spring Web Flow所拥有的会话数据的大小是否超过物理堆的大小。

堆级群集

Terracotta for Spring使用面向方面的技术在类加载时调整应用程序。 在此阶段,它扩展了应用程序,以确保在整个集群中正确维护Java的语义,包括对象引用,线程协调,垃圾回收等。

前面我们还提到过Terracotta不使用序列化。 这意味着Spring Web Flow维护的任何对话都可以在整个集群中共享。 这也意味着Terracotta不会将会话状态的整个对象图发送给所有节点,而是将图分解为纯数据,而仅通过电线发送实际的“增量”,这意味着实际的变化-在其他节点上为“陈旧”。

由于它有一个中央协调器(请参阅下文),可跟踪谁在每个节点上引用谁,因此它可以以惰性方式工作,并且仅将更改发送到引用“脏”对象的节点。需要更改。 这将利用引用的局部性,并且如果负载平衡器配置为使用“粘性会话”,则将更加有效,因为这意味着某些数据将永远不必离开实际会话并复制到另一个节点。

该架构是基于中心和分支的,这意味着有一个中央协调员来管理客户。 在这种情况下,客户端只是与Terracotta for Spring运行时一起使用的常规应用程序。 协调器不是单点故障,但是您可以有任意数量的协调器待命,一旦发生故障,选定的协调器将在发生崩溃的主协调器停下来的地方接机。 这还允许您通过独立于客户端进行集群来扩展协调器。

编写高度可用的有状态Web应用程序

在这里,我们将使用一个名为Sellitem的示例应用程序来推动讨论并向您展示:

  1. 如何使用Spring Web Flow编写有状态的会话式Web应用程序。
  2. 如何使用Terracotta for Spring声明性地对有状态应用程序进行群集。

Sellitem示例应用程序是一个演示,可以在Spring Web Flow发行版中找到(有关更多信息,请参见本文结尾的“ 资源 ”部分)。

使用Spring Web Flow实现有状态的Web应用程序:Sellitem

Sellitem示例应用程序演示了条件转换,对话范围,流执行重定向和继续的混合。 引导用户浏览多个页面,这些页面使他/她可以指定商品的价格,待售商品的数量,折扣率,运输详细信息(如果需要),并在最后查看所有信息。

我们不会遍历该应用程序的所有源代码,而是将重点介绍如何配置Spring Web Flow导出的不同标准服务(bean)以及如何定义页面流(使用Spring Web Flow的DSL的DSL的XML版本)。

从Spring MVC配置DispatcherServlet

此应用程序的入口点是Spring MVC的标准DispatcherServlet,它在web.xml中注册并映射到Web应用程序上下文中的* .htm资源:

<servlet>
<servlet-name>sellitem</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/sellitem-servlet-config.xml
/WEB-INF/sellitem-webflow-config.xml
</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>sellitem</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>

DispatcherServlet的配置位于Spring配置文件sellitem-servlet-config.xml和sellitem-webflow-config.xml中。 sellitem-servlet-config.xml内部是映射到“ /pos.xml”URL的单个Controller,该控制器将对该URL的所有请求分派到Spring Web Flow系统(其入口点是流执行器):

<bean name="/pos.htm"  class="org.springframework.webflow.executor.mvc.FlowController">
<property name="flowExecutor" ref="flowExecutor" />
</bean>

配置流执行程序和流注册表Bean

将Spring的flowExecutor Bean配置为使用flowRegistry Bean执行位于/ WEB-INF / flows /目录中的基于XML的流定义。

<flow:executor id="flowExecutor" registry-ref="flowRegistry"/>

<flow:registry id="flowRegistry">
<flow:location path="/WEB-INF/flows/**-flow.xml" />
</flow:registry>

定义页面流

其余逻辑在我们在flowRegistry bean中注册的流定义中定义(请参见上面的“配置Flow Executor和Flow Registry bean”部分)。

在深入研究流实现细节之前,首先让我们看一下页面流的图形状态图(如下所示)。

在上方,我们可以看到流程在完成之前需要经过几个步骤,并且存在一个决定状态,该状态确定是否需要销售才能进行销售。

下面显示了一个很好的初始流定义,该定义仅实现了上面的导航规则(并且还没有行为):

<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd">

<var name="sale" class="org.springframework.webflow.samples.sellitem.Sale"/>

<start-state idref="enterPriceAndItemCount"/>

<view-state id="enterPriceAndItemCount" view="priceAndItemCountForm">
<transition on="submit" to="enterCategory"/>
</view-state>

<view-state id="enterCategory" view="categoryForm">
<transition on="submit" to="requiresShipping"/>
</view-state>

<decision-state id="requiresShipping">
<if test="${flowScope.sale.shipping}" then="enterShippingDetails" else="finish"/>
</decision-state>

<view-state id="enterShippingDetails" view="shippingDetailsForm">
<transition on="submit" to="finish"/>
</view-state>

<end-state id="finish" view="costOverview"/>

</flow>

正如我们所看到的,上面的定义具有与状态图图的状态相对应的状态,以及与图中的箭头相对应的转换。 “ sale” bean是在流程开始执行时分配的流程实例变量。 它是有关销售属性的持有人。

上面的定义清除了所有导航逻辑,但尚未实现任何应用程序行为。 具体来说,尚未编写在用户提交事件时更新Sale Bean的逻辑。 另外,尚未定义后端销售处理逻辑。

完整的Spring Web Flow定义实现了所有必需的行为,如下所示:

<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd">

<var name="sale" class="org.springframework.webflow.samples.sellitem.Sale"/>

<start-state idref="enterPriceAndItemCount"/>

<view-state id="enterPriceAndItemCount" view="priceAndItemCountForm">
<render-actions>
<action bean="formAction" method="setupForm"/>
</render-actions>
<transition on="submit" to="enterCategory">
<action bean="formAction" method="bindAndValidate">
<attribute name="validatorMethod" value="validatePriceAndItemCount"/>
</action>
</transition>
</view-state>

<view-state id="enterCategory" view="categoryForm">
<transition on="submit" to="requiresShipping">
<action bean="formAction" method="bind"/>
</transition>
</view-state>

<decision-state id="requiresShipping">
<if test="${flowScope.sale.shipping}" then="enterShippingDetails" else="processSale"/>
</decision-state>

<view-state id="enterShippingDetails" view="shippingDetailsForm">
<transition on="submit" to="processSale">
<action bean="formAction" method="bind"/>
</transition>
</view-state>

<action-state id="processSale">
<bean-action bean="saleProcessor" method="process">
<method-arguments>
<argument expression="flowScope.sale"/>
</method-arguments>
</bean-action>
<transition on="success" to="finish"/>
</action-state>

<end-state id="finish" view="costOverview">
<entry-actions>
<action bean="formAction" method="setupForm"/>
</entry-actions>
</end-state>

<import resource="sellitem-beans.xml"/>

</flow>

现在,除了定义导航逻辑之外,该流程还定义了在正确的时间调用适当的应用程序行为的操作。 这包括处理用户提交事件和调用后端销售处理器以处理销售的逻辑。

表单绑定和验证

当进入显示表单的视图状态时,该流程将调用FormAction命令Bean以执行表单设置和提交逻辑。 提交后,FormAction将用户请求参数绑定到适当的销售属性,并在其中进行验证。

<bean id="formAction" class="org.springframework.webflow.action.FormAction">
<property name="formObjectName" value="sale"/>
<property name="validator">
<bean class="org.springframework.webflow.samples.sellitem.SaleValidator"/>
</property>
</bean>

想要查询更多的信息

有关Spring Web Flow及其10个示例应用程序(包括Sell Item)的完整代码和文档,可以在Spring网站http://www.springframework.org/webflow上找到

集群Sellitem应用程序

因此,现在我们已经看到了如何使用Spring Web Flow实现对话式Web应用程序。 现在让我们更有趣,看看如何通过Terracotta for Spring对其进行群集以提供透明的容错能力并在群集节点之间共享状态,从而为示例应用程序启用高可用性和故障转移。

听起来很难? 好吧,如果事实证明这很简单。

声明式配置

Sellitem示例应用程序正在使用Sale类的实例来存储当前销售的所有对话数据。 同样, Spring Web Flow的流执行存储库正在使用HTTP会话来存储所有会话数据。

为了启用Terracotta for Spring,我们需要指定为给定的Web应用程序启用HTTP会话群集,并包括所有可能存储在HTTP会话中(或可从存储在会话中的实例访问的类) ),用于检测。 这是Terracotta for Spring的tc-config.xml配置文件的示例:

<application>
<spring>
<jee-application name="swf-sellitem" >
<session-support>true</session-support>
<instrumented-classes>
<include>
<class-expression>
org.springframework.webflow.samples.sellitem.Sale
</class-expression>
</include>
</instrumented-classes>
</jee-application>
</spring>
</application>

在这里,我们为swf-sellitem WAR文件启用了HTTP会话集群,并包括了用于销售的Sale类。

就是这样,现在我们已经完成了很多工作。

启用兵马俑

剩下要做的唯一一件事就是为我们的应用程序启用Terracotta for Spring运行时。 这是通过修改Tomcat Web服务器的启动脚本并将以下环境变量添加到脚本顶部来完成的:

set JAVA_OPTS=-Xbootclasspath/p:"%DSO_BOOT_JAR%"
set JAVA_OPTS=%JAVA_OPTS% -Dtc.install-root="%TC_INSTALL_DIR%"
set JAVA_OPTS=%JAVA_OPTS% -Dtc.config="%LOCAL_DIR%\tc-config.xml"

其中:

  • DSO_BOOT_JAR环境变量设置为引导jar的位置(可以在用于弹簧安装的Terracotta根文件夹中的common / lib / dso-boot目录中找到)。
  • TC_INSTALL_DIR环境变量设置为Terracotta for Spring安装根目录。
  • LOCAL_DIR设置为包含tc-config.xml的文件夹。

可从下面的“资源”部分获得预配置为与Terracotta for Spring集群配置的Sellitem应用程序。 它还包含可以直接启动的Tomcat群集配置。

注意:在Spring应用程序上下文中对bean进行集群时,我们可以在服务(bean)名称级别上工作,并依靠Terracotta来实现Spring的自动包含检测机制,例如,在大多数情况下,我们不需要关心要包含哪些类,但是仅通过在tc-config.xml文件中指定它们的名称来定义我们要集群的bean。

摘要

Spring Web Flow提供了一种编写有状态会话Web应用程序的好方法,从简单的应用程序(如我们在本文中看到的)到具有许多丰富页面流的大型企业应用程序,这些都有状态的Web应用程序。 Terracotta for Spring为您的Spring Web Flow应用程序带来了高可用性。

简而言之, Terracotta for Spring提供:

  • 基于Spring Web Flow的应用程序(包括常规Spring应用程序) 的容错能力
  • 跨多个分布式节点透明共享应用程序状态 ,无需实现java.lang.Serializable
  • 跨多个分布式节点维护资源协调
  • 在多个分布式节点之间维护按引用传递语义
  • 声明性配置, 几乎无需更改现有代码 (除非Spring应用程序显式为无状态,而需要改为有状态)

Spring Web Flow和Terracotta for Spring一起为您提供了一个新的维度,可以编写有状态的,可对话的,可伸缩的和高度可用的Web应用程序。

资源资源

Spring Web Flow

主站点,下载和文档http : //www.springframework.org/webflow

演示应用程序Spring Web Flow发行版附带了本文中介绍的Sellitem应用程序。

在线试用Sellitem应用程序http : //spring.ervacon.com/swf-sellitem/

Spring兵马俑

Terracotta for Spring是Open Terracotta项目的一部分,该项目提供了开源JVM级别的集群http : //terracotta.org/

下载: http : //terracotta.org/confluence/display/orgsite/Download

演示应用程序 :Terracotta for Spring发行版附带了简化的Sellitem应用程序版本,该应用程序已预先配置(甚至捆绑了Tomcat和负载均衡器),并且可以直接运行。

文档http : //terracotta.org/confluence/display/docs1/Spring+Quick+Start

翻译自: https://www.infoq.com/articles/spring-web-flow-terracotta/?topicPageSponsorship=c1246725-b0a7-43a6-9ef9-68102c8d48e1

terracotta

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值