你如何处理无状态 grails 服务中的共享数据

Posted

技术标签:

【中文标题】你如何处理无状态 grails 服务中的共享数据【英文标题】:How do you deal with shared data in stateless grails service 【发布时间】:2016-07-18 15:22:18 【问题描述】:

我试图实现一个 grails SearchService 索引某些文本并将其存储在内存中以便更快地查找。为了存储这些数据,我试图在服务中使用私有静态属性来存储数据,但该属性是随机重置值。重读文档后,我意识到这很可能是因为 grails 服务应该是无状态的,因为员工是单例模式。不过,我不确定我是否了解静态变量如何变化。 JVM 是否为每个线程加载单独的服务类副本?不确定我是否完全了解正在发生的事情。

尽管如此,既然我知道我不能依赖静态变量来存储应用程序范围的数据,那么在保持同步和避免竞争的同时,存储和访问数据以供跨应用程序使用的最佳方法是什么?


原因:java.lang.IllegalStateException:类 [TEXTSTORE] 上的方法在 Grails 应用程序之外使用。如果在使用模拟 API 或引导 Grails 的测试环境中正确运行。 在 SearchService.buildIndex(SearchService.groovy:63) 在 SearchService$_indexAllDomains_closure2.doCall(SearchService.groovy:42) 在 SearchService.indexAllDomains(SearchService.groovy:41) 在 SearchService.$tt__rebuildIndex(SearchService.groovy:48) 在 SearchService.afterPropertiesSet(SearchService.groovy:35) ... 4 更多

【问题讨论】:

嗯,当您的代码更改导致服务重新加载时,您是否看到这些服务在生产或开发过程中不可靠?自 Grails 1.x 以来,我一直在使用各种方法在服务中保持共享状态(例如查找或索引数据),并且从未在生产中看到过这种情况。一次都没有。 正在开发中。如果服务抛出 NPE 错误并且未明确捕获(仍在解决一些错误),则该问题是可重现的。这种情况下类会重新加载吗? 如果您更改类,它们会在开发中重新加载,因此这实际上可能是您看到此问题的原因。您确实应该通过挂钩到 bean 生命周期并让它在启动时重新填充/加载它的数据来使您的服务更加可靠。通常让您的服务实现 org.springframework.beans.factory.InitializingBeanafterPropertiesSet() 是这样做的一个很好的介绍。 谢谢,乔希。没有考虑过,会调查的。 【参考方案1】:

您似乎对 Grails 中的服务有点困惑。服务(默认为单例)没有理由不能共享状态。服务在创建时填充一些缓存或索引数据以供多个调用者使用的情况并不少见。

这通常是通过实现org.springframework.beans.factory.InitializingBean 接口并使用afterPropertiesSet() 方法来完成的,该方法在应用程序上下文中创建服务(Spring bean)并且所有依赖关系都已解决时调用。

例如:

package com.example

import org.springframework.beans.factory.InitializingBean

class MyExampleService implements InitializingBean 
  private List data
  def otherService

  void afterPropertiesSet() 
    data = otherService.doSomethingToFetchData()
  
  // .. other stuff

通过挂钩 bean 的生命周期,您可以相当确定即使在开发中(当您的服务因为您更改了一些代码而重新加载时)它仍然具有所需的数据。

【讨论】:

乔希,这确实有帮助,但我立即遇到了另一个问题。我正在尝试从数据库中的一些数据创建索引。但是,在启动服务时,域对象似乎还没有准备好使用,我得到以下信息。 引起:java.lang.IllegalStateException:类 [TEXTSTORE] 上的方法在 Grails 应用程序之外使用。如果在使用模拟 API 或引导 Grails 的测试环境中正确运行。在 SearchService.buildIndex(SearchService.groovy:63) 在 SearchService$_indexAllDomains_closure2.doCall(SearchService.groovy:42) 在 SearchService.indexAllDomains(SearchService.groovy:41) 在 SearchService.$tt__rebuildIndex(SearchService.groovy:48) 在 SearchService。 afterPropertiesSet(SearchService.groovy:35) ... 4 更多 这似乎是一个单独的问题,与应用程序启动期间 GORM 的设置方式和使用的类加载器有关。我建议发布有关此问题的新问题,因为它不是您遇到的原始问题,实际上是一个新问题/问题。

以上是关于你如何处理无状态 grails 服务中的共享数据的主要内容,如果未能解决你的问题,请参考以下文章

Windows 如何处理无符号 64 位整数?

你如何处理 Angular 中的函数顺序?

你如何处理数据库关系模式中的递归关系N:M

你如何处理大量的小文件?

ApolloClient:你如何处理缓存中的规范化/嵌套?

一文教你如何处理高并发