Java的:高性能的消息传递(单生产者/单消费者) [英] Java: High-performance message-passing (single-producer/single-consumer)

查看:245
本文介绍了Java的:高性能的消息传递(单生产者/单消费者)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最初问这个问题<一href=\"http://stackoverflow.com/questions/3367192/java-is-while-true-loop-in-a-thread-bad-whats-the-alternative\">here,但我意识到,我的问题不是一个,而真循环。我想知道的是,什么是做高性能异步消息传递在Java中?有道

I initially asked this question here, but I've realized that my question is not about a while-true loop. What I want to know is, what's the proper way to do high-performance asynchronous message-passing in Java?

我试图做...

我有〜万消费者,从他们的专用队列每个消费消息。我有一个线程的生产的消息一个接一个,并把他们在正确的消费者的队列。每个消费者无限循环,检查的消息出现在其队列并进行处理。

I have ~10,000 consumers, each consuming messages from their private queues. I have one thread that's producing messages one by one and putting them in the correct consumer's queue. Each consumer loops indefinitely, checking for a message to appear in its queue and processing it.

我认为词是单生产者/单消费者,因为有一个生产者和每个消费者只能在自己的私人队列(多个消费者不要在同一个队列中读取)。

I believe the term is "single-producer/single-consumer", since there's one producer, and each consumer only works on their private queue (multiple consumers never read from the same queue).

在Consumer.java:

Inside Consumer.java:

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

制片人以飞快的速度把消费者的消息队列内的消息(每秒几百万的消息)。消费者应以最快的速度处理这些消息越好!

The Producer is putting messages inside Consumer message queues at a rapid pace (several million messages per second). Consumers should process these messages as fast as possible!

注:在,而(真){...} 是由生产者发送作为其最后一个消息的KILL消息终止

Note: the while (true) { ... } is terminated by a KILL message sent by the Producer as its last message.

不过,我的问题是关于设计这个消息传递的正确方法。我应该使用什么样的队列,为的MessageQueue?它应该是同步或异步的?应该如何信息来设计?我应该使用,而真循环?如果消费者是一个线程,或者其他什么东西?将万线程放慢到爬行?什么是替代线程?

However, my question is about the proper way to design this message-passing. What kind of queue should I use for messageQueue? Should it be synchronous or asynchronous? How should Message be designed? Should I use a while-true loop? Should Consumer be a thread, or something else? Will 10,000 threads slow down to a crawl? What's the alternative to threads?

因此​​,什么是做高性能的消息传递在Java中?有道

推荐答案

我要说的是10000线程上下文切换的开销将是非常高的,更不用说内存开销。默认情况下,在32位平台上,每个线程使用256KB的默认堆栈大小,所以这是2.5GB只是你的筹码。显然,你说64位,但即便如此,相当多的大量的内存。由于所使用的内存量,高速缓冲存储器将被颠簸地段,并且CPU将由存储器带宽被节流。

I would say that the context switching overhead of 10,000 threads is going to be very high, not to mention the memory overhead. By default, on 32-bit platforms, each thread uses a default stack size of 256kb, so that's 2.5GB just for your stack. Obviously you're talking 64-bit but even so, that quite a large amount of memory. Due to the amount of memory used, the cache is going to be thrashing lots, and the cpu will be throttled by the memory bandwidth.

我会寻找那些避免使用这么多线程来避免分配大量的协议栈和上下文切换开销设计。你不能同时处理的线程万。当前硬件具有通常小于100芯。

I would look for a design that avoids using so many threads to avoid allocating large amounts of stack and context switching overhead. You cannot process 10,000 threads concurrently. Current hardware has typically less than 100 cores.

我会在一个循环的方式创建每个硬件线程和调度消息一个队列。如果处理时间有很大的不同,有一些线程处理完他们的队列中给予他们更多的工作之前,而其他线程从来没有通过自己的工作分配得到的危险。这可以通过使用工作窃取来避免,如在JSR-166 ForkJoin框架实现

I would create one queue per hardware thread and dispatch messages in a round-robin fashion. If the processing times vary considerably, there is the danger that some threads finish processing their queue before they are given more work, while other threads never get through their allotted work. This can be avoided by using work stealing, as implemented in the JSR-166 ForkJoin framework.

由于通信是从发布给订阅者的一种方式,则消息并不需要任何特殊的设计,假设订户一旦已出版不改变消息

Since communication is one way from the publisher to the subscribers, then Message does not need any special design, assuming the subscriber doesn't change the message once it has been published.

编辑:阅读注释,如果有10,000个符号,然后创建通用的用户线程(每个核心一个用户线程)一把,那asynchornously从发布者(例如,通过他们的消息队列)收到的消息。订户从队列中拉消息,检索消息的符号,并在地图消息处理程序看起来这件事,检索处理程序,并调用处理程序来同步处理消息。一旦这样做,它重复,取从队列中下一个消息。如果相同的符号信息必须按顺序进行处理(这就是为什么我猜你想万队列。),你需要的符号映射到用户。例如。如果有10个用户,那么符号0-999去订户0,1000-1999为用户1等更精确的方案是根据它们的频率分布地图符号,从而使每个用户得到大致相同的负载。例如,如果流量的10%是符号0,则订户0将处理只是一个符号和其它符号,对其他的用户之间进行分配。

Reading the comments, if you have 10,000 symbols, then create a handful of generic subscriber threads (one subscriber thread per core), that asynchornously recieve messages from the publisher (e.g. via their message queue). The subscriber pulls the message from the queue, retrieves the symbol from the message, and looks this up in a Map of message handlers, retrieves the handler, and invokes the handler to synchronously handle the message. Once done, it repeats, fetching the next message from the queue. If messages for the same symbol have to be processed in order (which is why I'm guessing you wanted 10,000 queues.), you need to map symbols to subscribers. E.g. if there are 10 subscribers, then symbols 0-999 go to subscriber 0, 1000-1999 to subscriber 1 etc.. A more refined scheme is to map symbols according to their frequency distribution, so that each subscriber gets roughly the same load. For example, if 10% of the traffic is symbol 0, then subscriber 0 will deal with just that one symbol and the other symbols will be distributed amongst the other subscribers.

这篇关于Java的:高性能的消息传递(单生产者/单消费者)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆