【问题标题】:With 2 web servers, will a singleton class have 2 instances?如果有 2 个 Web 服务器,一个单例类会有 2 个实例吗?
【发布时间】:2011-03-08 07:26:26
【问题描述】:

如果有 2 个 Web 服务器,一个单例类会有 2 个实例吗?

【问题讨论】:

  • @David 这是一个公平的问题,如果您不是这些方面的专家,您可能会认为集群网络服务器共享 JVM。事实上,如果存在这样的系统,我一点也不感到惊讶,尽管我怀疑它们是否被普遍使用。
  • @David M:此外,对于正在学习设计模式但还不知道单例的“陷阱”的初学者来说,这可能是一个有用的问题/答案

标签: c# java oop


【解决方案1】:

两个网络服务器都有各自的应用程序实例,无论是 .net 还是 java。所以是的,两个服务器都将拥有您的单例类的单独实例。

不管这两个web服务器是两台不同的物理机,即使在同一台服务器上,也肯定会完全运行在不同的进程上。每个进程都会将其对象加载到内存中,与任何其他进程分开。

specifically in case of asp.net - 即使在单个 Web 服务器中,每个站点都会导致单独的 Singleton 类实例。因为 asp.net 工作进程中的每个站点都加载在单独的应用程序域中,所以没有两个域可以相互干扰对方的对象。因此,在 asp.net 的情况下,即使是具有单个 asp.net 工作进程的单个 Web 服务器也可以/将具有单个类的多个实例,每个实例彼此分开。

【讨论】:

  • 很好的答案。很高兴看到您涵盖了工作进程,直到每个请求都独立于其他请求这一事实。很多开发者都忘记了这一点。
  • 每个请求还是每个网站?每个网站可能都有自己的应用程序域,但听起来您是在说每个 Web 请求?困惑。
【解决方案2】:

是的,每个 JVM 甚至类加载器都有一个 Singleton。

请参阅这篇 When is a Singleton not a Singleton? 文章(适用于 Java)。

【讨论】:

    【解决方案3】:

    “2 个网络服务器”是什么意思? 静态字段(在单例中)的范围为应用程序域(在 .net 中)。

    因此,如果您的两台 Web 服务器在两个独立的应用程序域中运行,则可以,否则不可以。

    【讨论】:

      【解决方案4】:

      事实上,如果它是部署两次的 web 应用程序的一部分,那么您很可能在一个 web 服务器中有 2 个单例调用实例。

      在 Java 中,类加载器是类标识的一部分。你可以用不同的类加载器加载同一个类两次,所有的静态字段都会存在两次。 C# 也有类似的机制。

      【讨论】:

      • 通过类加载器你的意思是像tomcat这样的容器对吗? (对于网络应用)
      • @Blankman:不,我的意思是 java.lang.ClassLoader 类。像 tomcat 这样的容器对它们部署的每个应用程序使用不同的类加载器,从而防止它们相互干扰;每个应用程序都可以有其单独的单例类实例,并且每个应用程序都可以使用同一类的不同版本。
      【解决方案5】:

      可以创建一个多路复用所有内容的 Web 服务器 - 连接、侦听套接字,甚至接口。它仍然是该类的一个实例,只有一个线程,并且在此之上还有一个非常小的内存占用。需要注意的是,虽然从最实际的角度来看,它看起来像两台服务器,但它仍然只是一台服务器(如果它崩溃,它会整个崩溃......)

      不过,这种方法并不像多线程网络服务器那样流行,因为虽然硬件较轻,但开发人员更难处理 - 您必须在所有内容之间显式多路复用,并在非阻塞调用中处理所有连接。如果您产生一些额外的线程,操作系统会为您节省大量工作,让您更轻松地编写功能更丰富的服务器。

      当然,即使在单线程服务器中,仍然可以在单独的任务中生成第二台服务器,只需用户/管理员/再次执行二进制文件的人,使用不同的配置。需要一些非常花哨的编程来防止这种情况发生。

      【讨论】:

        【解决方案6】:

        这就是为什么 JSP/Servlet 提供“会话”和“应用程序”数据的概念。这些应该在多服务器环境中的服务器之间共享。

        【讨论】:

          【解决方案7】:

          作为这个问题的延伸,特别是对于 .NET web 应用,你还需要注意 SessionState 的处理。假设会话不是“粘性的”(一旦建立会话,用户就停留在一个 Web 服务器上),您需要将 SessionState 更改为进程外。这可以是 ASP.NET 会话状态服务器,也可以是 SQL Server,但要记住的关键点是 SessionState 不会在服务器之间自动共享,除非您通过进程外进行共享。此外,您放入 SessionState 的任何内容都需要可序列化;将 [Serializable] 属性添加到您在 SessionState 中使用的任何类。

          【讨论】:

          • 不是主题,同意,但这很可能是他将遇到的下一个问题。
          猜你喜欢
          • 1970-01-01
          • 2020-09-22
          • 2023-03-30
          • 2017-01-11
          • 2015-12-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多