naquda
V2EX  ›  Java

如何在 1s 内广播消息到 30K 甚至更多的客户端?

  •  
  •   naquda · Nov 2, 2015 · 7117 views
    This topic created in 4026 days ago, the information mentioned may be changed or developed.

    具体是这样的, 现在有个服务,是基于 JAVA Netty 的,
    有一个线程在不断产生数据,基本每一秒都会有新的数据,当这个数据产生后,需要尽快的发送到所有关心这个数据的客户端,对时间很敏感,最敏感的, 1S 内都要发送完。
    Netty 的话,我看用 ChannelGroup.write() 也没有并发的执行

    有什么样的方案可以做到这样的事情?
    查了一些资料,有些在 JAVA 上实现轻量级线程,比如 Quasar , 但具体应用资料很少。
    另外, Golang 是不是很容易干这种事情?

    26 replies  •  2015-11-15 09:22:56 +08:00
    ritksm
    ritksm
    Nov 2, 2015
    1
    MQ 消息 fanout
    naquda
    naquda
    OP
    Nov 2, 2015
    2
    @ritksm 麻烦能否说得详细一点
    jedihy
    jedihy
    Nov 2, 2015
    3
    如果你这里的广播不是指的 IP broadcast 的话, 1s 30K 有可能理论上都发不出去啊。你要计算一下消息大小 X 30K X 1s 是多少数据量,你的带宽够吗?实现的话,可以用非阻塞 IO 来发,搞 N 个进程,每个进程上跑一个非阻塞 IO 。把消息分发到这些进程然后让他们发送,把 CPU 和网卡资源利用满。
    naquda
    naquda
    OP
    Nov 2, 2015
    4
    @jedihy 消息本身不大,一个消息 20byte 左右, 1S 30K ,带宽应该不是问题,但是这个消息时间敏感,需要尽快的发出去
    目前是这样的, 客户端会去主动去问服务端拿新的消息,这个消息在服务端,是由其他线程更新的(一个写, N 个读),但有时候,会刚好在消息被更新之前,拿到老的消息,导致客户端要再次不断去问服务器拿新的消息,现在 Netty 来处理这个并发是没问题的
    但我想,有么有可能服务端在消息更新的时候,主动发送到每个关心它的客户端,主要是要尽可能快的发送给所有客户端,
    用进程或者线程池来处理,还是很麻烦, 因为有不止一个消息,几乎没秒都有消息在更新,然后关心这个消息的客户端有多也有少,多的夸张点,有 30K , 少点也有几 K ,
    所有我找到有 JAVA 的轻量级线程实现比如 Quasar , 但,我还不知道可不可以,以及怎么和 NETTY 一起用
    patrickstar
    patrickstar
    Nov 2, 2015
    5
    如果不能多播估计是不现实的, java 不懂,看看你采用的中间件的能力
    chinawrj
    chinawrj
    Nov 2, 2015
    6
    @naquda 只要消息小于 1K ,对于网卡的负载影响不是很大吧。反正你要一秒内发送 30K 个 skb_buf 。先用 C 语言写个微型 TCP server ,然后用 30K 的客户端测试一下。看看能不能搞定这个事情。也就半天就能写好的事情。目测一般服务器搞不定
    beneo
    beneo
    Nov 2, 2015
    7
    消息中间件不就是干这个的么?非要自己写?
    beneo
    beneo
    Nov 2, 2015
    8
    rabbitmq
    fsneak
    fsneak
    Nov 2, 2015 via iPhone
    9
    嗯…虽然我不是很熟悉…不过 netty 的线程模型应该是每个客户端连接的读写都是单线程的,每个线程处理多个连接,有多个这样的线程吧?既然最底层是这样,那再在上层考虑并发应该没啥意思吧…?
    AstroProfundis
    AstroProfundis
    Nov 2, 2015
    10
    这样的需求应该搞个消息中间件...典型场景...
    yghack
    yghack
    Nov 2, 2015
    11
    单服务器搞不定的。
    master13
    master13
    Nov 2, 2015
    12
    把客户端的名字改为“ 30K ”,然后 1 秒钟发给他......
    lhbc
    lhbc
    Nov 2, 2015 via iPhone
    13
    用 UDP ,不要用 TCP
    你的消息只有 20 Byte ,但是加上 TCP 握手等开销,流量多了好几倍。

    随便一个高级语言都能搞定。
    ixiaohei
    ixiaohei
    Nov 2, 2015
    14
    赶紧 1 秒钟单机干不了
    ixiaohei
    ixiaohei
    Nov 2, 2015
    15
    感觉 打错了
    Tabata
    Tabata
    Nov 2, 2015
    16
    用一楼的 MQ 方式:ActiveMQ 或者 RabbitMQ Topic 模式
    SparkMan
    SparkMan
    Nov 2, 2015
    17
    推荐使用 ZeroMq (“史上最快的消息队列”),用发布订阅模型。跟上面说的 ActiveMQ 或者 RabbitMQ 完全不同,他俩的速度肯定跟不上; ZeroMQ 不能持久化,但是特别快,是要取代 socket 的
    SparkMan
    SparkMan
    Nov 2, 2015
    18
    ActiveMQ 或者 RabbitMQ 之所以觉得慢,是因为跟 Kafka 比要慢很多,所以推荐你用 ZeroMQ
    Comdex
    Comdex
    Nov 2, 2015
    19
    golang 的 nsq
    naquda
    naquda
    OP
    Nov 2, 2015
    20
    谢谢各位, 先研究一下各位提供的方案
    znoodl
    znoodl
    Nov 2, 2015 via iPhone
    21
    zeromq push pull
    znoodl
    znoodl
    Nov 2, 2015 via iPhone
    22
    错了 pub sub
    eycfsjd
    eycfsjd
    Nov 2, 2015
    23
    @SparkMan 能否分享一下 rabbitmq 比 kafka 慢很多的场景?我以前做过 2 组测试,消息大小分别为 1k 与 40kb 的时候, rabbitmq 与 kafka ( batch 设为 100 )性能不相上下。
    naquda
    naquda
    OP
    Nov 2, 2015
    24
    研究了下 ZeroMQ , 目前还很难用上这些技术, 主要是因为这个客户端也要做相应的修改,而我这的客户端比较特殊,并不是 X86 平台, PORTING 这些库,带来更多的未知风险, 所以还是要在传统的 SOCKET 上实现
    pkking
    pkking
    Nov 2, 2015
    25
    socket 中的广播或者多播可以满足你
    ncisoft
    ncisoft
    Nov 15, 2015 via Android
    26
    @pkking +1
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   4554 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 53ms · UTC 06:13 · PVG 14:13 · LAX 22:13 · JFK 01:13
    ♥ Do have faith in what you're doing.