Web 应用程序服务器端的负载平衡是否会生成 JSF 的单例 AppScoped bean 的多个实例?

Does load balancing in the server side of a web app generate multiple instances of a singleton AppScoped bean of JSF?

假设我在 AWS 或 GAE 上部署了我的 Web 应用程序,而我在 JSF 中的应用程序有一个带有方法 "void setList( List)" "List getList()" 的单例 ApplicationScoped Bean。 当用户对列表进行修改时,我从 SessionScoped bean 调用此方法。 我想通过向他们推送通知消息来确保所有用户在他们自己的会话中获得更改,以便他们可以再次获取列表。 如果 AWS 或 GAE 的负载均衡器将应用程序拆分为多个实例,他们如何管理这个单例 ApplicationScoped bean?有很多单例实例吗?它们是如何同步的?一个实例有不同的信息是否有任何风险?

我想参与负载平衡的每个服务器中的所有应用程序实例都需要以某种方式更新,但这会破坏负载平衡的目的,因为工作将在各处复制。单身人士的工作可能没有负载平衡,但我不知道。文档非常广泛,很难熟悉。

@ManagedBean( name = "theModelBean",
              eager = true )
@Singleton
@ApplicationScoped

public class ModelBean {
  ArrayList<Data> theList;

  public List<Data> getList(){
    return theList;
  }

  public void setList( List<Data> aList ) {
    this.theList = aList;
  }
}


@ManagedBean( name = "theController" )
@SessionScoped

public class Controller {

  @ManagedProperty(value = "#{theModelBean}")
  private ModelBean theModelBean;

  public foo(){
    ArrayList<Data> list = new ArrayList<>;
    list.add( new Data() );
    theModelBean.setList( list );
  }
}

我希望负载平衡不会干扰我的逻辑,并且它以透明的方式为我处理所有事情。否则,我可能不得不让 ModelBean 每次更改列表时将列表写入数据库,并在每次会话请求时从那里获取它。

我将忽略您问题中的 "load balancing" / "load balanced" 术语,并假设您实际上是指 "clustering" / "clustered"。如:同一个 WAR 文件被部署到多个服务器,这些服务器都在一个代理之后(谁做实际的负载平衡,但负载平衡本身不是观察到的问题的原因)。

是的,集群中的每个服务器都将获得自己的任何 "application scoped" bean 实例。这不仅包括 JSF @javax.faces.bean.ApplicationScoped,还包括 CDI @javax.enterprice.context.ApplicationScoped@javax.inject.Singleton 以及 EJB @javax.ejb.Singleton.

通常的方法确实是跟踪集群中所有服务器使用的单个公共数据源中的共享数据。通常使用 SQL-based RDBMS。通常,您会在每个 request/view 上触发一个 SQL 查询以从数据库中获取最新数据。如果为此使用 JPA,通常会使用二级缓存来缓存数据,从而减少数据库命中率。这个可以配置cluster-wide.

如果数据是不可变的(即创建后 read-only),那么在数据库中保存的另一种方法是依赖会话持久性。有一个 @SessionScoped bean,它在 writeObject() 期间从 @ApplicationScoped 读取,在 readObject() 期间从 writes-if-absent 读取到 @ApplicationScoped。在 JSF <f:websocket> 和 OmniFaces <o:socket>.

背后的代码中实现了一个真实世界的示例