什么决定了同时连接的数量

在Java servlet环境中,有哪些因素是同时用户数量的瓶颈。

  1. 服务器可以允许每个端口的HTTP连接数
  2. 服务器可以跨多个端口允许的HTTP连接数(我可以在多个HTTP端口上有多个WAS配置文件)
  3. 池中的servlet数
  4. 为WAS配置用于服务连接的线程数
  5. RAM可用于服务器(假设应用程序中存在0内存泄漏,服务线程数之间是否有任何相关性)

还有其他因素吗?

编辑:为了使业务逻辑脱离图片,假设只有一个servlet在Log4j上打印一行。

  • 我的Tomcat服务器可以同时处理6000个HTTP连接吗? 为什么不(文件处理?每个请求的CPU时间?)?
  • 我可以将线程池​​大小设置为5000(空闲线程是否占用CPU / RAM)?
  • 我可以将oracle连接池大小设置为500个连接(空闲连接是否需要CPU / RAM)?

每个连接生成的垃圾量是否会产生影响? 例如,如果对于每个HTTP连接,由Tomcat创建并留下20KB的对象,则在处理2500个请求时将使用100MB堆,这可能会触发300毫秒的GC暂停。

我们可以这样说:如果Tomcat使用0.2秒的CPU时间来处理单个HTTP请求,那么它将能够在一秒钟内处理大约500个http连接。 因此,6000个连接需要5秒。

有趣的问题,如果我们将所有性能决定属性分开,最后归结为你在servlet中做了多少工作,或者如果它具有最高的I / O,CPU和内存需要花费多少时间。 现在让我们向下移动,并列出上述说法; –

服务器可以允许每个端口的HTTP连接数

文件描述符有限制 ,但这又是由servlet完成请求的时间或从请求第一个字节接收到完成发送整个响应所花费的时间再次触发的。 因为如果它只需要1ms并且您正在使用Netty和持久连接,那么您可以达到非常高的>> 6000。

池中的servlet数

理论上>> 6000。但有多少线程正在处理您的请求? 是否有一个线程池正在烧毁您的请求? 所以你想增加线程,但多少可以说2000并发线程。 您的CPU在上下文切换时表现不佳吗? 它受I / O限制吗? 如果是,那么上下文切换是有意义的,但是你会遇到那些网络限制,因为很multithreading在网络I / O上等待,所以最终你花了多少时间在一项工作上。

D B

如果它是oracle,用连接管理祝福你,你肯定需要在这里进行严格的监控。 现在这只是另一个限制因素,可以被视为另一个阻塞I / O. 根据I / O的定义,延迟/吞吐量很重要,并且当它变得比最小的工作更大时成为瓶颈。

因此,最后,您需要细分所有servlet的以下或更多属性

  1. 是CPU绑定的吗? 如果是,它需要多少循环,或者可以安全地转换为某个时间单位。 例如1ms用于计算工作。
  2. 是I / O绑定,如果是,同样找到单位。
  3. 和别的
  4. 您拥有的一长串清单,例如CPU,内存,GB / s

现在您知道需要完成多少工作,而您所做的就是除以您所拥有的并继续调整,以便您找到最佳状态并找出您未考虑的其他属性并考虑它们。

我遇到的最大瓶颈是处理请求所需的时间。 您可以更快地为请求提供服务,您可以处理的连接越多。

由于每个应用程序都不同,这是一个难以回答的问题。 为了解决我支持的应用程序,我创建了一个生成许multithreading的unit testing,并在eclipse中观察VisualVM中的内存使用情况。

您可以看到内存消耗如何随正在使用的线程数而变化。 你应该能够获得一个线程转储,看看线程使用了多少内存。 您可以推断出平均值,以了解N个用户可能需要多少RAM。

瓶颈将是一个移动目标,因为你将优化一个区域,直到你可以扩大规模,然后另一个区域将成为你的瓶颈。

如果servlet的响应时间是瓶颈,您可以使用一些排队数学来确定可以根据平均响应时间以最佳方式排队多少请求。

http://www4.ncsu.edu/~hp/SSME_QueueingTheory.pdf

希望这可以帮助。

更新以解决您的其他问题:

我的Tomcat服务器可以同时处理6000个HTTP连接吗? 为什么不(文件处理?每个请求的CPU时间?)?

这可能但可能不是。 如果您计划进行高容量,也应该在应用程序服务器前面添加一个Web层。
假设您的应用程序中有6000个用户。 用户发送的每个请求仅存在于服务器上[希望],并且您的峰值线程数可能从未超过20。
我建议设置一些监控,以了解您的应用程序在实际使用情况下的表现。 查看http://Hawt.io ,它使用Jolokia通过http获取JMX指标。
如果您认真对待分析,我建议使用像Graphite这样的东西来聚合您的JMX指标。 https://github.com/graphite-project/graphite-web
我为Jolokia编写了一个收集器,用于向Carbon / Graphite发送指标,并且可以在我的管理层批准的情况下开源。 如果您有兴趣,请告诉我。

我可以将线程池​​大小设置为5000(空闲线程是否占用CPU / RAM)?

尽管设置线程池太高可能会让应用程序服务器接收太多请求,但空闲线程并不需要担心。 如果发生这种情况,您最终可能会因为无法处理的连接而充斥您的数据库,或者您的内存分配可能不足以处理这么多请求。 这可能会降低整体应用程序性能。
设置得太低,您的应用服务器可能会再次启动排队请求,从而导致性能下降。
通常在峰值或高音量时间内进行一些排队,但您不希望重载应用程序服务器。 查看排队理论以了解更多相关信息。
此外,这是在应用服务器前面有一个Web服务器可以帮助您的地方。 如果您使用Apache提供静态内容,则在大多数情况下,只有动态请求才会到达应用程序服务器。
调整非常适合您的个人应用。 我建议保留默认值并优化代码,直到你可以收集足够的数据来知道应该转动哪个旋钮。

我可以将oracle连接池大小设置为500个连接(空闲连接是否需要CPU / RAM)?

与应用程序线程池大小相同的情况。 虽然DB的池大小应该比应用程序线程数小得多。
对于大多数Web应用程序来说,500将是太高,除非您的数量非常大,在这种情况下,您可能需要像Oracle RAC这样的数据库集群环境。
如果池设置得太高而您开始使用大量连接,则数据库硬件将无法跟上,最终会导致数据库服务器出现性能问题。
返回查询所需的时间可能会增加,从而导致应用程序响应时间增加。 “日志堵塞”效果。
使用概要分析或指标来确定正常使用下的活动数据库连接的平均数,并将其用作确定最大允许数的基准。

每个连接生成的垃圾量是否会产生影响? 例如,如果对于每个HTTP连接,由Tomcat创建并留下20KB的对象,则在处理2500个请求时将使用100MB堆,这可能会触发300毫秒的GC暂停。

数字会有所不同,但是是的。 还记得Full GC更受关注。 增量GC不会暂停您的应用程序。 查看“并发标记和扫描”和“垃圾优先”。

我们可以这样说:如果Tomcat使用0.2秒的CPU时间来处理单个HTTP请求,那么它将能够在一秒钟内处理大约500个http连接。 因此,6000个连接需要5秒。

当每个请求进入时,它并不那么容易,还有一些正在处理和完成。 查看排队理论以更好地理解这一点。 http://www4.ncsu.edu/~hp/SSME_QueueingTheory.pdf

还有另一个常见的瓶颈 :数据库连接池的大小。 但我还有一个注意事项:当你耗尽允许的HTTP连接数,允许服务请求的线程数时,你只会拒绝一些请求。 但是当你耗尽内存(例如,过多的会话中有太多数据)时,你可能会崩溃整个应用程序。

不同之处在于,在短时间内负载较重的情况下,当负载稍后下降时:

  • 在第一种情况下,应用程序已启动并可正常处理请求
  • 在第二种情况下,应用程序已关闭,必须重新启动

编辑:

我忘了记住真实的用例。 我发现服务大量并发连接的最大问题是数据库请求的质量(假设您使用数据库)。 由于没有最大数量,因此没有直接影响,但您可以轻松地占用所有数据库服务器资源。 数据库请求不佳的常见示例:

  • 在具有大量行的表上没有索引
  • 一个不使用任何索引的请求(在一张大桌子上)
  • n + 1综合症:当你总是需要来自集合的数据时,当你将一个到多个关系映射到一个集合时,使用ORM
  • load full database syndrome :当您将所有关系映射为eager时,使用ORM,任何单个请求都会在加载大量依赖数据时结束。

这些问题更糟糕的是,当数据库很年轻时,它们不会对测试造成任何伤害,因为没有那么多行,但随着时间和行数的增加,性能下降给少数用户带来了无法使用的应用。

服务器可以允许每个端口的HTTP连接数

除内核资源外无限制,例如FD,套接字缓冲区等。

服务器可以跨多个端口允许的HTTP连接数(我可以在多个HTTP端口上有多个WAS配置文件)

由于每个端口的连接数是无限的,这无关紧要。

池中的servlet数

除非增加传入请求的速率,否则不相关。

为WAS配置用于服务连接的线程数

间接相关,见下文。

RAM可用于服务器(假设应用程序中存在0内存泄漏,服务线程数之间是否有任何相关性)

如果它限制线程数低于上面提到的配置线程数,则相关。

基本限制是请求服务时间。 越短越好。 它越长,线程在该请求中占用的时间越长,等待队列越长,…排队理论规定“最佳位置”不超过服务器利用率的70%。 除此之外,等待时间随着利用率的提高而迅速增长。

因此,任何有助于请求服务时间的事情都很重要:例如,线程池大小,连接池大小,并发瓶颈,……

您还应该考虑用例本身限制并发数量。 想象一下行动顺序重要的协作环境。 这会强制您同步操作 – 即使您已经能够同时处理所有操作。

在java land中,这可能是一个简单的事情,因为共享一个使用阻塞访问的资源。 (例如,共享随机数生成器(不是每个线程),共享向量,并发结构,如ConcurrentHashMap等)。

同步越多,您就越不能充分利用服务器硬件。

因此,除了耗尽内存或使CPU饱和或达到垃圾收集限制之外,这种同步可能是一个问题,不仅需要在代码中解决,而且甚至可能需要您软化高级工作流的某些要求。

看点6,您可以使用这些工具来查看您的硬件是否是瓶颈:假设您使用的是Linux,您可以使用VmStat查看有关RAM使用情况的一些统计信息, topatop (取决于您的发行版)看看你的CPU和RAM, nloadiftop会对你的网络带宽产生影响的过程,以及iotop看你的磁盘读写内容。