由于遗留系统不能同时处理来自同一用户的多个请求,我需要限制并发呼叫量。目标是将对服务的并发请求数限制为1 pr。用户(会话) - 但 不 使其阻止所有用户。我可以在客户端排队所有的ajaxrequests,但这似乎是一个只适用于某些调用的问题的大锤解决方案。如果可能的话,我想在服务器端解决这个问题。
替代。 1:可能的问题可能是自动服务的服务是代理 (由于requestcope)由spring注入并注入代理 引用可能会随请求而变化?或者Spring重用相同的代理 - 在这种情况下它会起作用吗?
@Scope("session")
public class Model {
@Autowired
Service service;
public List<Pojo> getPojos() {
synchronized(service) {
if(!hasTriedToRetrievePojos) {
hasTriedToRetrievePojos = true;
service.getPojos();
}
}
}
}
@Scope("request")
// Actually a LegacyService, wrapping an old legacysystem
public class Service {
...
}
替代。 2:如果Spring只构造了这个Model pr的一个实例。这应该按预期工作。
@Scope("session")
public class Model {
private Object lock = new Object();
@Autowired
Service service;
public List<Pojo> getPojos() {
synchronized(lock) {
if(!hasTriedToRetrievePojos) {
hasTriedToRetrievePojos = true;
service.getPojos();
}
}
}
}
替代。 3:在Model中注入HttpSession并在HttpSession 属性 上手动同步(根据Is HttpSession thread safe, are set/get Attribute thread safe operations?中最受欢迎的答案)。没有春天的混乱,但更麻烦。
鉴于您使用粘性会话,我对会话参数的重新同步应该是安全的,即使在一个融合的环境中也是如此?
答案 0 :(得分:0)
我赞成您的第二个解决方案,但在同步之前进行检查(这是昂贵的)并在同步块中进行另一次检查。
public List<Pojo> getPojos() {
if (!hasTriedToRetrievePojos) {
synchronized(lock) {
if (!hasTriedToRetrievePojos) {
hasTriedToRetrievePojos = true;
service.getPojos();
}
}
}
}
服务实例应该是单例,只要它在实例级别不包含任何用户/会话相关状态。
此解决方案的优势在于同步仅封装在Model
中,并且不依赖于Service
的正确配置(如第一个解决方案 - 例如服务上的@Scope("singleton")
会导致不同的行为)。除此之外,第一个解决方案也应该有效。您可以使用@Scope("request")
而不是@Scope("session")
。
如果粘性会话意味着用户的会话被绑定到一个appserver实例,并且每个用户的请求都被定向到这个实例,我会说是的,这是安全的。