java - 在 session 范围内的 spring-bean 中同步实例变量以限制对遗留服务的并发请求

标签 java spring concurrency httpsession

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

替代品。 1:可能的问题可能是 Autowiring 服务是代理 (由于 requestscope)由 spring 注入(inject)并且注入(inject)的代理 引用可能会因请求而改变?或者 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。 session 这应该按预期工作。

@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:在模型中注入(inject) HttpSession 并在 HttpSession property 上手动同步(根据 Is HttpSession thread safe, are set/get Attribute thread safe operations? 中最受欢迎的答案)。没有spring的困惑,反而比较繁琐。

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

最佳答案

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

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

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

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

如果粘性 session 意味着用户的 session 绑定(bind)到一个应用程序服务器实例,并且该用户的每个请求都定向到该实例,我会说是的,它是安全的。

关于java - 在 session 范围内的 spring-bean 中同步实例变量以限制对遗留服务的并发请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14890348/

相关文章:

java - fragment 转换的问题

java - 对 apache 磁贴属性进行逻辑处理

子信号和父信号之间的并发竞争

java - 如何从 Java 运行 Maven?

java - 如何通过多线程迭代concurrentLinkedQueue?

java - kubernetes 上的 Spark 作业失败,没有特定错误

重复来自 spring boot rest Controller 的 JSON 响应

java - hibernate : Why is it trying to drop/create database on startup?

java - 使用线程池时出现错误 FutureTask@2c7b84de 被拒绝

java - 具有静态方法和初始化方法的类的并发