在使用web服务时避免多次调用



我有一个任务,其中用户使用来自第三方的XML。XML提要每天只更新一次。XML存储在数据库中,并在请求时返回给用户。如果XML不在数据库中,则从第三方检索它,存储在数据库中,然后返回给用户。所有后续请求都将简单地从数据库中读取XML。

现在我的问题是。假设对第三方的请求需要10秒才能返回。在此期间,有多个服务器调用相同的数据。我不希望每一个都向第三方发出请求,也不希望用户什么都没有收到或收到错误。它们可能应该等待第一个请求完成,此时XML将可用。这是一个相对简单的问题,但我想知道解决它的最佳方法是什么。

我只是使用一个简单的标志来控制请求或可能像一个信号量?是否有更好的解决方案基于我打算使用的堆栈,即Play框架和cassandra后端。我能用回调或触发器做点什么吗?

顺便说一下,我需要在第一个请求进来时延迟加载数据。因此,在此任务中,不能在单独的进程中或在应用程序启动时获取数据…

谢谢

您所需要做的就是创建一个单独的组件,负责从第三方获取XML并将其保存到数据库。
在你的代码中,不同的线程试图从这个组件中"获取"XML
该组件返回数据库中存在的XML。如果不存在,则使用ReentrantLock进行同步。
因此,执行trylock时,只有一个线程成功。其余的将被封锁。当锁被释放时,其他线程被解除阻塞,但是XML已经被第一个设法获得锁的线程从第三方获取并存储到数据库中。所以其他线程只是从DB返回XML

示例代码(这只是一个"伪代码",让您开始。你应该处理异常等,但可以使用主框架。不要finally中忘记unlock,这样你的代码就不会无限期地阻塞):

public String getXML() {  
  String xml = getXMLFromDatabase();  
  if(xml == null) {  
     if(glocalLock.tryLock()) {  
        try{  
            xml = getXMLFromThirdParty();  
            storeXMLToDatabase(xml);       
        }  
        finally {  
            globalLock.unlock(); //ok! got XML and stored in DB. Wake-up others!  
        }  
     }
    else {  
         try{ //Another thread got the lock and will do the query. Just wait on lock!     
             globalLock.lock();  
         }  
         finally {
             //woken up but the xml is already fetched  
             xml = getXMLFromDatabase();  
             globalLock.unlock();  
         }   
     }    
  return xml;  
}

最新更新