草庐IT

Java:高性能消息传递(单一生产者/单一消费者)

coder 2024-03-29 原文

我最初问过这个问题 here ,但我意识到我的问题不是关于 while-true 循环。我想知道的是,在 Java 中进行高性能异步消息传递的正确方法是什么?

我正在尝试做什么......

我有大约 10,000 个消费者,每个消费者都从他们的私有(private)队列中消费消息。我有一个线程一条一条地生成消息并将它们放入正确的消费者队列中。每个消费者无限循环,检查消息是否出现在其队列中并处理它。

我相信这个术语是“单一生产者/单一消费者”,因为只有一个生产者,每个消费者只在他们的私有(private)队列上工作(多个消费者永远不会从同一个队列中读取数据)。

Consumer.java 内部:

@Override
public void run() {
    while (true) {
        Message msg = messageQueue.poll();
        if (msg != null) {
            ... // do something with the message
        }
    }
}

生产者正在快速地将消息放入消费者消息队列中(每秒数百万条消息)。消费者应该尽快处理这些消息!

注意:while (true) { ... } 由生产者发送的 KILL 消息作为其最后一条消息终止。

但是,我的问题是关于设计此消息传递的正确方法。 messageQueue应该用什么样的队列?它应该是同步的还是异步的? Message应该怎么设计?我应该使用 while-true 循环吗? Consumer 应该是一个线程,还是其他什么东西? 10,000 个线程会慢得像爬行一样吗?什么是线程的替代品?

那么,在 Java 中进行高性能消息传递的正确方法是什么?

最佳答案

我会说10,000个线程的上下文切换开销会非常高,更不用说内存开销了。默认情况下,在 32 位平台上,每个线程使用 256kb 的默认堆栈大小,因此 2.5GB 仅用于您的堆栈。显然你说的是 64 位,但即便如此,那还是相当大的内存量。由于使用的内存量,缓存会出现大量抖动,并且 cpu 会受到内存带宽的限制。

我会寻找一种避免使用太多线程的设计,以避免分配大量堆栈和上下文切换开销。您不能同时处理 10,000 个线程。当前的硬件通常少于 100 个内核。

我会为每个硬件线程创建一个队列,并以循环方式发送消息。如果处理时间差异很大,则存在这样的危险,即某些线程在分配给它们更多工作之前就完成了队列处理,而其他线程则永远无法完成分配给它们的工作。这可以通过使用在 JSR-166 ForkJoin 框架中实现的工作窃取来避免。

由于通信是从发布者到订阅者的一种方式,因此 Message 不需要任何特殊设计,假设订阅者在消息发布后不会更改消息。

编辑:阅读评论,如果您有 10,000 个符号,则创建一些通用订阅者线程(每个核心一个订阅者线程),它们异步接收来自发布者的消息(例如,通过他们的消息队列)。订阅者从队列中拉取消息,从消息中检索符号,并在消息处理程序的映射中查找它,检索处理程序,并调用处理程序以同步处理消息。完成后,它会重复,从队列中获取下一条消息。如果必须按顺序处理相同符号的消息(这就是为什么我猜你想要 10,000 个队列。),你需要将符号映射到订阅者。例如。如果有10个用户,则符号0-999到用户0,1000-1999到用户1等。更精细的方案是根据频率分布映射符号,这样每个用户得到大致相同的负载。例如,如果 10% 的流量是符号 0,则订阅者 0 将只处理该符号,而其他符号将分配给其他订阅者。

关于Java:高性能消息传递(单一生产者/单一消费者),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3367383/

有关Java:高性能消息传递(单一生产者/单一消费者)的更多相关文章

  1. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  2. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

  3. ruby - rails 3 redirect_to 将参数传递给命名路由 - 2

    我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use

  4. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  5. ruby-on-rails - 如何生成传递一些自定义参数的 `link_to` URL? - 2

    我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些

  6. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  7. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  8. ruby - 使用 Ruby 通过 Outlook 发送消息的最简单方法是什么? - 2

    我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=

  9. Ruby - 如何将消息长度表示为 2 个二进制字节 - 2

    我正在使用Ruby,我正在与一个网络端点通信,该端点在发送消息本身之前需要格式化“header”。header中的第一个字段必须是消息长度,它被定义为网络字节顺序中的2二进制字节消息长度。比如我的消息长度是1024。如何将1024表示为二进制双字节? 最佳答案 Ruby(以及Perl和Python等)中字节整理的标准工具是pack和unpack。ruby的packisinArray.您的长度应该是两个字节长,并且按网络字节顺序排列,这听起来像是n格式说明符的工作:n|Integer|16-bitunsigned,network(bi

  10. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

随机推荐