一尘不染

跨JVM同步方法

java

如何跨JVM同步方法?

我的示例是一个Web应用程序,该应用程序限制一个用户名不能多次登录(换句话说,第一个用户可以登录,但是如果另一个用户使用相同的用户名登录,他将被拒绝)。

该Web应用程序部署在多个服务器上,因此有多个JVM,并且用户可以尝试使用不同的服务器进行登录,具体取决于负载平衡器。

这是该方法的外观

public synchronized static SessionData logonSync(String userName, String password) throws Exception 
{
    int count = DB.count("sessions", "WHERE user_name=?", userName);
    if (count > 0)
    {
       throw new Exception("logon.error.loginAlreadyUsed");
    }

    return logon(userName, password);
}

由于采用了同步方法,因此它可以在1个应用服务器上正常工作,但是可以跨多个JVM?两个用户可能试图同时登录不同的Web应用程序。我该如何预防?

编辑 如果您的解决方案希望利用某些事务性缓存方法,则该应用程序也使用Memcached。


阅读 152

收藏
2020-12-03

共1个答案

一尘不染

您询问有关跨JVM同步方法的问题。这就需要一个处理分布式进程的库。有很多选择,这里只是几个:

  1. Terracotta-支持将某些字段配置为在JVM之间“共享”,因此您可以使用标准的JVM锁定,例如synced关键字,它可以在多个JVM上使用。
  2. JGroups -Jgroups是用于分布式应用程序的工具包。锁定是它提供的功能之一。这是他们文档中的一个例子

无论使用哪种库,设置分布式锁定都不是一件容易的事。如果需要的话,很好,但是对于您的示例,这似乎有点过头了。其他选项:

  • 在数据库中添加唯一性约束,让其强制执行唯一性。这可能会对数据库的性能产生影响,因此它实际上取决于您希望获得多少流量。
  • 让负载均衡器使用用户名(或用户名的哈希)作为用于将请求分配给Web服务器的密钥。这将确保来自同一用户名的请求每次都将到达同一Web服务器-不需要分布式锁,只需使用常规锁即可。
2020-12-03