REST服务:防止每个用户进行并发调用

时间:2017-09-05 16:06:19

标签: java rest web-services concurrency resteasy

我正在开发一个REST服务(使用RESTeasy),它执行大量计算并产生大量结果(将被下载到文件中)。 为了保护系统,我们决定通过阻止并发调用来限制同一用户的执行。

我想在会话中添加一个变量,如下所示:

//check if service is running before execution
if (Boolean.parseBoolean((String) session.getAttribute("isRunning"))) {
        throw new WebApplicationException(Response.status(
        Response.Status.FORBIDDEN).entity("Service is currently running!").build());
}

//on execution
session.setAttribute("isRunning", "true");

//after execution
finally {
    session.setAttribute("isRunning", "false");
}

但这会限制每次会话不是每个用户

2 个答案:

答案 0 :(得分:1)

你走在正确的轨道上。

在会话中存储一个集合(我将其称为UserSet)。

当你收到请求时, 执行以下操作:

  1. 识别用户。
  2. 应用程序范围获取UserSet。
  3. 在UserSet上进行同步。
  4. 检查用户是否已在UserSet中。
  5. 如果是,请将请求短路并退出Web服务电话。
  6. 如果不是,请将用户添加到UserSet。
  7. 退出同步块。
  8. 执行长时间运行。
  9. 在UserSet上进行同步。
  10. 从集中删除用户。
  11. 编辑:根据John Wu评论纠正范围。

答案 1 :(得分:0)

基于@dwb建议的方法,这是我的回答:

//globally defined set holding ids of users currently executing the service
private static Set<String> currentUsers = Collections.synchronizedSortedSet(new TreeSet<String>());


//check if service is running before execution
if (isCurrentlyRunningByUser(request.getRemoteUser())) {
        throw new WebApplicationException(Response.status(Response.Status.FORBIDDEN).entity("Service is currently running!").build());
}


//after execution
finally {
    currentUsers.remove(user);
}



/**
 * checks if user is currently running the service. if yes, returns true.
 * if no, add user to current users set, and returns false
 * @param remoteUser user asking to execute the service
 * @return true if service is being run by the user
 */
private boolean isCurrentlyRunningByUser(String user) {
    synchronized (currentUsers) {
        Iterator it = currentUsers.iterator();
        while (it.hasNext()) {
            if (user.equals(it.next())) {
                return true;
            }
        }
        currentUsers.add(user);
    }
    return false;
}