4

由于遗留系统不能同时处理来自同一用户的多个请求,我需要限制并发调用的数量。目标是将服务的并发请求数限制为 1 pr。用户(会话) - 但不要让它在所有用户中阻塞。我可以在客户端对所有 ajax 请求进行排队,但这似乎是对仅适用于某些调用的问题的大锤解决方案。如果可能的话,我想在服务器端解决这个问题。

替代。1:可能的问题是自动装配服务是spring注入的代理(由于requestscope),并且注入的代理引用可能会随着请求而改变?或者 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:在模型中注入 HttpSession 并在 HttpSession属性上手动同步(根据Is HttpSession thread safe, are set/get Attribute thread safe operations?)。没有弹簧混乱,但更麻烦。

鉴于您使用粘性会话,即使在集群环境中,我对会话参数的同步也应该是安全的?

4

1 回答 1

0

我会赞成您的第二个解决方案,但在同步之前进行检查(这很昂贵)并在同步块中进行另一次检查。

public List<Pojo> getPojos() {
     if (!hasTriedToRetrievePojos) {
         synchronized(lock) {
             if (!hasTriedToRetrievePojos) {
                 hasTriedToRetrievePojos = true;
                 service.getPojos();
             }
         }
     }
}

只要服务实例在其实例级别不包含任何用户/会话相关状态,它就应该是单例的。

该解决方案的优点是同步Model仅被封装,不依赖于正确的配置Service(如在第一个解决方案中 - 例如@Scope("singleton"),服务会导致不同的行为)。除此之外,第一个解决方案也应该有效。而不是@Scope("request")你可以使用@Scope("session").

如果粘性会话意味着用户的会话绑定到一个 appserver 实例,并且该用户的每个请求都被定向到该实例,我会说是的,它是安全的。

于 2013-02-15T14:44:48.367 回答