草庐IT

java - 维护拥有大量线程的 Java 应用程序时,我需要了解什么?

coder 2024-03-11 原文

背景信息

我有一个进行数据分析的分布式处理应用程序。它旨在对实时更新的多组数据进行并行处理。作为设计的一部分,分析已分解为分析节点。每个节点获取源数据并对其进行处理以创建其他数据,然后这些数据又可以被其他节点使用。要对一个数据集进行我们当前的全套分析,需要大约 200 个节点。

在目前的设计中,每个节点都有自己的线程运行。现在,大部分时间这些线程都处于 hibernate 状态。每当数据更新时,它们都会像瀑布一样轮流醒来,然后又回到 sleep 状态。该应用程序目前正在生产中运行 40 组数据,每组需要 200 个节点,使用 8000 个线程。当没有数据进来时,服务器上就没有负载。当数据在最繁忙的时候进入时,服务器的 CPU 占用率会飙升至 25% 左右。这都在项目的设计和生产参数范围内。

下一步,我们将 40 组数据扩展到 200 组。每组需要 200 个节点,即总共 40000 个节点,即 40000 个线程。这超过了我们服务器的最大 PID,所以我要求我们的服务器管理员增加上限。他们做到了,并且应用程序可以运行,但是他们给了我一些关于线程数量的反驳。我不否认线程数不寻常,但这是我们设计的这个阶段所预期和保证的。

我计划对设计进行一些小调整,以将线程与节点分开。这将允许我们配置一个线程来运行多个节点,并减少我们的线程数。对于不经常更新的数据集,让一个线程在每个节点执行数据更新对性能的影响非常小。对于每秒更新数百次的数据集,我们可以将每个节点配置为在自己的线程上运行。事实上,我并不怀疑这种设计改变将会发生——只是时间问题。与此同时,我希望尽可能多地了解使用此设计的后果。

问题

在一台机器上运行超过 40,000 个线程的成本是多少?让 JVM/Linux 操作系统管理这么多线程会损失多少性能?请记住,它们都已正确配置为在没有工作时 hibernate 。所以,我只是在谈论额外的开销和由线程数量过多引起的问题。

请注意 - 我知道我可以减少线程数,而且我知道进行此设计更改是个好主意。我会尽快完成,但它必须与其他工作和设计考虑因素相平衡。我问这个问题是为了收集信息,以便做出正确的决定。非常感谢您对这种性质的想法和评论。

最佳答案

What are the costs of running with over 40,000 threads on one machine? How much performance am I losing by having the JVM / Linux OS manage this many threads? Please remember that they are all configured properly to sleep when there is no work. So, I'm just talking about extra overhead and problems caused by the sheer number of threads.

在JVM空间中,每个线程都需要一个线程栈(默认256kb)以及Thread对象和连接对象。可以使用 -Xss 选项更改默认线程堆栈,但我相信 64kb 是下限。 (40,000 x 256kb 是 10Gb ...)

在 Linux 上,每个线程还占用一个 OS 线程描述符,这将在线程不执行时帮助线程注册上下文……以及其他东西。这些描述符是预先分配的,我相信它们没有被分页。这是您的管理员需要增加的资源。

无论线程是清醒还是 hibernate ,都会使用这些资源。

另一个问题是您需要小心使用 wait/notifyAll 进行同步。如果有很多线程在等待同一个对象,那么 notifyAll 将在每个线程被唤醒时引起一连串的 Activity 。 (但是你可以通过不让很多线程等待同一个对象来避免这种情况。)

参见 Oracle Java Threading页面以获取有关使用大量线程的后果的更多信息。


我的感觉是 40,000 个线程过多。理想的线程数与您拥有的物理处理器/内核数成正比。虽然拥有大量线程不一定会导致性能下降,但您会占用大量资源,这可能会产生间接的性能问题;例如更长的 GC 时间,潜在的 VM 抖动。

对于您的应用程序来说,更好的架构是实现线程池和工作队列,以将工作分配给数量少得多的 Activity 线程。

关于java - 维护拥有大量线程的 Java 应用程序时,我需要了解什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5716119/

有关java - 维护拥有大量线程的 Java 应用程序时,我需要了解什么?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby - 我需要将 Bundler 本身添加到 Gemfile 中吗? - 2

    当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/

  3. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  4. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  5. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  6. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  7. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  8. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  9. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  10. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

随机推荐