naquda
V2EX  ›  Java

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

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

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