【问题标题】:How to implement asynchronous notification in a three tier, web service backend, desktop application?如何在三层、Web 服务后端、桌面应用程序中实现异步通知?
【发布时间】:2011-09-06 00:39:37
【问题描述】:

我们有一个 ERP 应用程序。服务器端实现为一系列使用 Hessian 和 Spring 公开的 Web 服务。 Web 服务使用 DAO 层进行所有数据库操作。 DAO 是使用 Hibernate 实现的。客户端是 Java Swing。它利用 Web 服务进行所有与数据相关的操作。

问题在于,如果有另一个客户端同时编辑同一行,则需要阻止某些行被编辑。此外,每当客户端完成编辑行时,所有其他客户端都应使用更新后的值更新该行。该解决方案必须考虑到客户端可能会显示相同的数据但具有不同的视图(例如,相同的数据在一个客户端中被过滤,而在另一个客户端中未被过滤)。

客户端之间的套接字连接是不可能的,因为应用程序需要通过防火墙工作而无需额外配置。不断轮询服务器以获取更新并不能很好地扩展,因为我们在这里查看了数百个并发客户端。

查看我的选择,我考虑过 JMS,但在花了 2 天时间尝试使用 Spring 配置 ActiveMQ 之后,我终于放弃了(我以前没有使用 JMS 的经验,团队也没有)。尽管如此,对于我们在这里需要的东西来说,它似乎太复杂了。最后,我使用优秀的Java-WebSocket library 使用 websockets 实现了一些东西,并且在客户端上破解了一个新的表侦听器、单元格编辑器和表模型之后,它正在工作。

我仍然担心客户端负责跟踪可编辑/不可编辑的单元格、添加和删除的行等。从我的角度来看,这个解决方案太脆弱了。在任何给定的时间,一条消息都可能丢失,所有客户端的状态之间都失去同步。

我的问题是,在当前架构下,您将如何实现这一要求?如果更改后端是一种选择,您会进行哪些更改以使此要求更易于实现?在我看来,Web 服务架构的无状态特性,加上我们使用 Hibernate 并且我不知道在请求正在修改可能分离的对象时收到通知的事实,使事情变得比他们应该做的更复杂是。

【问题讨论】:

    标签: java web-services notifications desktop-application


    【解决方案1】:

    由于提到的 Web 服务的无状态特性,除了维护和定期查询/更新特定记录的锁定状态(锁定所有者、锁定类型、时间戳等)之外,别无其他。并且不要忘记超时:“他打开了编辑记录并切断了他的网络电缆或去度假”。从我给定布局中的 pov 解决方案来看,它是否有效并不重要。例如,我会选择 JMS,它会查看锁定数据库并处理锁定/解锁/保活消息。

    但是当锁定机制不是ERP不可或缺的一部分时,最大的问题不是“如何锁定”,而是“锁定什么”: 当有人添加新的采购订单条目时,我应该能够编辑采购订单的标题吗?总会计师修改客户信用额度时,是否可以开立新的应收账款?等等。在我看来,从顶层对象到业务逻辑再到摆动输入字段,实现这样的逻辑几乎和从头开始创建新的 ERP 一样难。

    【讨论】:

      【解决方案2】:

      我认为您实际上是在安排自己必须编写自己的消息传递总线。

      我不明白您为什么要让客户作为其修改内容的唯一登记者负责。

      通常,客户端“签出”存储库中的资源,存储库管理员有责任注册谁签出了哪些资源。

      你有三层:

      • 后端数据存储库
      • 中间层信息控制器
      • 前端客户端。

      更糟糕的是,我们假设您有一个分布式数据存储库。东京的变化需要实时同步到伦敦、新加坡、上海和纽约。

      实时

      首先,您需要了解和定义“实时”的含义。实时是允许防止进程失相的最大时间延迟。甚至,您的进程可以容忍的异相量内的最大延迟时间。

      异相意味着您正在从前一个流程运行/决策周期接收数据,以配置当前流程运行/决策周期。

      在战斗机中,实时意味着微秒或纳秒。在炼油厂,实时可能意味着 10 毫秒甚至秒。在全球制造业务中,实时可能意味着一个工作班次为八小时。

      在您的情况下,您需要定义两组实时延迟

      • 具有存储库的存储库控制进程。
      • 与客户端的存储库控制流程。

      让我们假设,虽然与问题无关,但全球存储库同步的实时性为 4 小时,即存储库和存储库控制进程之间允许的最大延迟时间为 4 小时,而不是秒。这将为您的客户端级同步提供足够的呼吸空间。

      存储库看板

      我使用非标准术语看板来强调令牌的作用,以便您可以在该术语上搜索并了解其含义。

      存储库控制过程将是看板管理器/寄存器。客户端不应该是已签出哪些资源的寄存器。会有各种类型的看板

      • 阅读看板
      • 写看板
      • 状态转换/事件看板

      您会了解读写令牌的用途,但什么是状态更改令牌?在 ERP 和 MRP 中,状态转换和事件构成了系统监控和管理流程的能力的支柱。假设某个资源正在“休假”,“休假返回”事件会触发该资源的状态更改。

      当然,您没有使用事件和状态来管理您的 ERP,因为您在“编辑”行时会密切注意要锁定的其他行。但是,如果您可以重写您的应用程序以使用事件和状态会更好,因为您的存储库控制器应该只管理较低级别的读写同步,将资源互锁留给资源-事件-状态模型。

      因此,每个客户都会查看看板,了解他们正在阅读/阅读的资源。每当客户端提交更新时,看板就会返回给控制器,然后控制器会定位已签出的其他看板的插槽 - 以便向这些订阅者发送有关更改的消息。

      在实时定义的限制下,您或您的应用程序必须决定可以为特定资源分配多少看板。必须对可以通知多少订阅者保持现实,这样基于人类和基于机器的用户才不会做出无法容忍的不合时宜的决定。以及一个控制器可以管理多少个客户端套接字。

      如果您正在实施排队/级联状态转换模型,您还需要定义一个资源允许分配多少个状态转换看板。我想再次强调,为 ERP 实施资源事件/转换状态模型而不是硬编码 if-then-else 逻辑会有多大帮助。为此,您需要熟悉状态机并成为状态机极客。您可能会说,嘿,用户只需要更新价格记录。但是您没有意识到,正是更新造成了状态变化,必须通过资源网络传播。

      允许注册该更改并通知订阅者该更改的时间延迟是多少 - 以防止机器或人在接收更新之前触发相关事件。当然,控制器会拒绝过渡看板的异相请求,但为了提高效率和用户友好性,您需要尽量减少这种情况。

      网络服务同步

      客户端会通过请求调用 Web 服务。 Web 服务检查该资源的必要看板是否可用。请记住,Web 服务会话必须与看板的其他实例竞争。如果您实现了资源事件/转换状态模型,您的应用将知道要排列哪些看板以及是否可以级联多个修改以供不同的客户端检出。

      updateGrade(resourceA){
        case (Extreme):
        updatePrice(resourceA);
        case (Premium):
        notify(productMgrA)
        case (Downgrade):
        scrap (ProductA)
      }
      

      如果某个客户正在等待对 ProductA 的某些材料进行处置,并计划花费一些资源/人力来实现这一目标,而报废 (ProductA) 可能即将发生,该怎么办?首先,您的用户的资源事件状态模型定义 updateGrade 将请求 ProductA 的状态转换看板,并且任何其他进程/客户端将无法获取看板来更改带有 ProductA 标记的资源的状态。

      我不确定我是否已经解决了您的问题,但我只是在宣传使用状态机建模为您的应用程序带来的好处以及它在多大程度上满足您的消息传递需求时,我度过了一段美好的时光。并且不应该使用编写的源代码或SQL来直接执行资源互锁。

      我还想说,我曾使用状态转换图和矩阵训练用户如何定义他们的流程。这意味着您也必须享受这样做。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-01-17
        • 2012-04-20
        • 1970-01-01
        • 2011-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多