V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
unt
V2EX  ›  程序员

Java Go Node 哪种语言最适合做物联网平台开发

  •  
  •   unt · 318 天前 · 5609 次点击
    这是一个创建于 318 天前的主题,其中的信息可能已经有所发展或是发生改变。
    设备量:10W 台同时在线,同时收发
    对接方式:mqtt,tcp ,websocket (设备种类较多,每种设备不同的对接协议)
    公司背景:中型企业,toB,本公司说了算,出现 bug 也没事
    68 条回复    2023-07-29 17:38:07 +08:00
    zbatman
        1
    zbatman  
       318 天前   ❤️ 3
    有请 Rust 方辩手登场
    Presbyter
        2
    Presbyter  
       318 天前
    曾经做过 lorawan, 我们使用的是 mqtt + go + nats 组建的核心网.
    当时选择使用 go 也是因为其网络能力强一些, 当然如果但是 rust 成熟些, 我们可能就选用 rust 了, 因为 leader 是 C 出身......
    yazinnnn
        3
    yazinnnn  
       318 天前
    iot 用 java 需要大量 netty 的相关技能, 如果研发水平参差不齐的话, 建议用 go

    另外用 node 是图啥...
    Nazz
        4
    Nazz  
       318 天前   ❤️ 2
    10W 在线量一个 go wbesocket server 实例就够了. 我们最近在跑百万连接压测: https://github.com/lesismal/go-websocket-benchmark
    hhjswf
        5
    hhjswf  
       318 天前 via Android
    go
    coderxy
        6
    coderxy  
       318 天前
    用 go 吧。 多协议兼容也很方便。 性能也没啥问题
    runningman
        7
    runningman  
       318 天前
    go ,绝对是 go
    BBCCBB
        8
    BBCCBB  
       318 天前   ❤️ 1
    toB 我建议你用 Java, Netty 有大量现成协议支持. mqtt 什么的也有现成方案.

    当然 10w 的量级,你说的这几个任何一个都可以完成..
    unt
        9
    unt  
    OP
       317 天前
    关于量级:
    大项目会私有化部署,不会走我们的云平台。
    云平台上能做到 10W 的话我们项目也有几千万的体量的了,到时候领导就会重视起来,研发投入就不会再是个问题。
    unt
        10
    unt  
    OP
       317 天前
    非常感谢各位的解答🙏
    INCerry
        11
    INCerry  
       317 天前   ❤️ 3
    楼主限定了几种语言,我肯定用 C#,其实几十万同时在线这种需求对于现在有协程 /异步 IO 的开发语言压力都不大,工业物联网这个.NET 成熟和开源的项目蛮多了,基本支持各种协议和驱动,包括一些 PLC 、串口设备都支持。

    举个例子: https://github.com/iioter/iotgateway
    liqinliqin
        12
    liqinliqin  
       317 天前   ❤️ 3
    我推荐 swoole
    xingjue
        13
    xingjue  
       317 天前
    物联网绝对 go 必须 go
    smallmin97
        14
    smallmin97  
       317 天前
    请问下 MQTT Broker 的选型是哪个?我司目前用的是 EMQX 开源版,同时在线数量是 3.5 w 。
    wangritian
        15
    wangritian  
       317 天前
    必然用协程模型,开发最方便的就是 go 了
    wbuntu
        16
    wbuntu  
       317 天前
    推荐用 go ,做过类似的物联网项目,服务端对接不同设备,解析二进制协议用 go 比较方便,客户端如果是带 OS 的,用 go 编译出多架构的程序也比较方便
    dudubaba
        17
    dudubaba  
       317 天前
    都能实现那建议用自己熟练且相对热度不高的,既然有决定权不背锅,技术就掌握在自己手上。
    coder001
        18
    coder001  
       317 天前   ❤️ 1
    看来用 dot net core 的只有我一个?
    coder001
        19
    coder001  
       317 天前
    @INCerry #11 WOW ,看来我井还没有没落,没太仔细读回帖就先莽了
    建议不要太过于 “迷信”(🤔?) Task/async/await 的调度机制,到头来可能还不如自己撸线程来的快 :p
    xumiao
        20
    xumiao  
       317 天前 via iPhone
    @smallmin97 请教一下,请问你们用的什么中间件存储数据呀🥹
    liantian
        21
    liantian  
       317 天前 via iPhone
    用 ceo cio cto 最擅长的…
    moonheart
        22
    moonheart  
       317 天前
    go 可以用 tinygo 这个嵌入式编译器 https://tinygo.org/
    zhuangzhuang1988
        23
    zhuangzhuang1988  
       317 天前
    erlang/elixir ??
    mmdsun
        24
    mmdsun  
       317 天前
    推荐个最近发现的物联网开源的项目。
    https://github.com/jetlinks/jetlinks-community

    支持统一物模型管理,多种设备,协议适配(TCP,MQTT,UDP,CoAP,HTTP),都很全。
    alsas
        25
    alsas  
       317 天前
    go 需要超高的并发性能
    flyqie
        26
    flyqie  
       317 天前
    @zhuangzhuang1988 #23

    总感觉现在只有游戏服务器用 erlang 了。。

    其他好像很少听到有用 erlang 的项目。
    westoy
        27
    westoy  
       317 天前
    c10k 你上个 python 都没问题.........
    liuhan907
        28
    liuhan907  
       317 天前   ❤️ 1
    @coder001
    除了纯 CPU 密集的东西---撇开 TPL 这套不谈---可能自己用线程会更好,其它的场景下还有默认调度器劣于手动线程的么?
    zjsxwc
        29
    zjsxwc  
       317 天前 via Android
    纯 php 的 workerman 也可以,甚至提供了用于轻松实现分布式架构的框架 gatewayworker ,轻松通过加机器来处理大流量。
    tairan2006
        30
    tairan2006  
       317 天前 via Android
    拿 go 写简单点
    AnroZ
        31
    AnroZ  
       317 天前
    建议 Golang ,不考虑成本直接上 Rust 。
    someonedeng
        32
    someonedeng  
       317 天前
    go

    开发简单,性能到位
    tomqin
        33
    tomqin  
       317 天前 via Android
    K8s 原生,Go 写的物联网开发平台不考虑一下?
    https://github.com/Edgenesis/shifu
    lysS
        34
    lysS  
       317 天前
    物联网都是有系统的吗?怎么动态语言都能用
    photon006
        35
    photon006  
       317 天前
    @yazinnnn node 擅长的就是 IO 密集型任务。
    cnbattle
        36
    cnbattle  
       317 天前
    同建议 go
    BigR
        37
    BigR  
       317 天前   ❤️ 1
    物联网,建议上 Erlang 。实时性比较好。
    lujiaxing
        38
    lujiaxing  
       317 天前   ❤️ 2
    没人提 C# 么... 做 IoT C# 简直不要更合适好吧...
    leeyuzhe
        39
    leeyuzhe  
       317 天前
    mqtt 十万台毛毛雨了吧
    hhjswf
        40
    hhjswf  
       317 天前
    @yazinnnn netty 框架封装了,做起来反而容易。go 啥都得自己亲力亲为。。
    ychost
        41
    ychost  
       317 天前
    性能这些语言都不在话下,主要看哪个出问题了能修问题
    yazinnnn
        42
    yazinnnn  
       317 天前
    @hhjswf 大多数 spring boy 写不了 netty
    coder001
        43
    coder001  
       317 天前
    @liuhan907 #28

    吾辈在 TCP 异步 Socket 高并发的情况下滥用了异步回调处理收到的数据,响应时间拉长到无法接受,排查发现是调度延迟。
    后来在 SocketAsyncEventArgs 回调把要处理的东西封装成工作项,放进自己维护的线程,用线程安全队列排队处理,这才扛得起来。

    这算 CPU 密集吗🤔 (不过这倒是和主题的物联网沾上边了
    WispZhan
        44
    WispZhan  
       317 天前 via Android
    中间件用 go ,平台化业务用 Java
    ssr 和 bff 用 node

    好全用上了🐶
    INCerry
        45
    INCerry  
       317 天前
    @coder001

    > WOW ,看来我井还没有没落,没太仔细读回帖就先莽了 建议不要太过于 “迷信”(🤔?) Task/async/await 的调度机制,到头来可能还不如自己撸线程来的快 :p

    协程主要是为了 IO 密集场景,用异步代替阻塞,用更少的线程做更多的事,IO 密集场景收益肯定更大的。对于单个 task 有延迟的问题肯定是客观存在的,毕竟线程数量更少了 ,任务多了线程任务队列就堆积了,解决方案也可简单,适当提升线程池线程数量,避免线程池饥饿就可以了,很多项目都会设置 MinThread 。
    oldshensheep
        46
    oldshensheep  
       317 天前
    用 Java 的 Vertx ,容易写好多,和 Go 和 JS 差不多,
    写 Vertx 就一种写 JS 的感觉,太舒服了。而且性能和 Netty 一样都是顶尖水平
    coder001
        47
    coder001  
       317 天前 via Android
    @INCerry #45
    当然尝试设置最小线程数量,但收效甚微,而且 CPU 使用率显著上升
    lincanbin
        48
    lincanbin  
       317 天前
    网络应用是 go 的主场。
    DOLLOR
        49
    DOLLOR  
       317 天前
    微软刚出了个 DeviceScript ,TypeScript 的子集,专门用于物联网开发。
    INCerry
        50
    INCerry  
       316 天前
    @coder001 我对于这块比较有经验,如果后面有遇到类似的问题,可以抓个 trace 和 dump ,一起分析下,总得来说那块应该不会有很大问题。
    liuhan907
        51
    liuhan907  
       316 天前
    @coder001
    我比较好奇你的场景使用了多少连接数和 PPS ,还有吞吐量。或者说你对延迟的需求很高?
    Desdemor
        52
    Desdemor  
       316 天前
    go 可以的,相对简单,并发用协程
    coder001
        53
    coder001  
       316 天前
    @INCerry #50
    @liuhan907 #51
    先谢过两位

    目前用若干个绑定了队列的线程,每次有回调就挑队列长度最短的分配工作项,压测看起来数据没这么难看了
    压测用 5 万个 TCP 同时打进去,PPS 没测量,几乎所有 PDU 都小于 1400 ,姑且按 PDU 计算的话,极端状况下往返加起来可能会达到( x4 ) 20 万 PDU 每秒。
    协议超时时间是 30 秒,但超过 10 秒就会被称为数据不好看
    liuhan907
        54
    liuhan907  
       316 天前
    @coder001
    怎么说呢,只有 5W 连接的情况下这个数据感觉有点奇怪。你的原始测试代码还有留存么?
    coder001
        55
    coder001  
       316 天前
    @liuhan907
    目前性能数据已经可以接受,就不放出来丢人现眼了 _(:з)∠)_
    liuhan907
        56
    liuhan907  
       315 天前
    @coder001
    我只是好奇为什么数据会这么差,因为和我之前压测的数据比差的不少。
    学习一下,以后避坑(
    coder001
        57
    coder001  
       315 天前
    @liuhan907
    那就简单来说说 (^ o ^)ノ

    测试环境是 linux k8s 集群,所在节点 4 核 16G (后来加到了 8 核),非独占,还有一些其他东西跑,但不占太多 CPU

    最开始的版本是图省事,嫌复杂懒得用 SocketAsyncEventArgs ( SAE ),监听开单线程阻塞,接收就用 Socket.Select 方法批量轮询,把筛出来的 Socket 滥用 Task.Run 处理接收和协议解析,可以想象线程池会有多窘迫,再多的 MinThread 也处理不过来,只会徒增 CPU 使用率。

    单线程阻塞监听真是太天真了,大量 TCP 同时发起的时候根本 accept 不过来,后来改用 SAE 监听,一上来就安排 1024 个躺在端口前迎接,回调不直接处理,而是放进自己创建的工作线程排队创建应用层会话,加入会话管理器。这下几乎没有连不进去的了。

    后来多几次改进调优就变成完全 SAE 了,监听和接收还有发送全都走 SAE ,只是 SAE 的回调依旧信不过,不在这里做过多的处理,而是自己开线程排队,也能观测一下队列数量来评估性能。

    总算是稍微拯救了一下这难看的数据。

    要问为什么自己撸 Socket 而不用现成框架,我不想回忆被 SuperSocket 折磨的那些年 _(:з)∠)_
    辩解:协议单一,而且相对简单,可以自己来❌
    liuhan907
        58
    liuhan907  
       315 天前   ❤️ 1
    @coder001
    搞明白了。Select 这个就不多说效率没眼看。至于 SAE 那个确实是专用 IO 线程更好。
    我建议你看一下 asp.net core 现在使用的那个抽象模式以及实现。我认为应该是目前比较好的答案了。
    主要代码在 aspnetcore 项目 src\Servers\Kestrel\Transport.Sockets\src 下面。
    BBCCBB
        59
    BBCCBB  
       314 天前
    我看大家都在说并发用 go 的协程.. 其实 go 的协程在 socket 量级 10w 这种, 如果你每个 socket 都开 2 个 goroutine, 20w 个协程, go 的调度压力很大的, 这种情况下不太适合有栈协程, 所以你看 go 里也有许多框架封装后就是 netty 的线程模型的样子. 几个 goroutine 就能处理所有 socket 的 IO.

    每个 socket 开两个协程, 写写玩具, 量不大的应用可以, 量上去了就不是这样玩的了.


    还是选择自己擅长的. 稳就对了.
    coder001
        60
    coder001  
       311 天前 via Android
    @liuhan907 #58
    源代码看起来有点枯燥,倒是发现原来 core 内置的 K 服务还能处理自定义 TCP 这就有意思了,正好有个新的小规模项目可以走这条路整整😋

    https://github.com/davidfowl/MultiProtocolAspNetCore/tree/master/KestrelTcpDemo
    liuhan907
        61
    liuhan907  
       311 天前
    @coder001
    aspnetcore 的代码可真是不容易看懂,稍有些绕。这个自定义处理 Tcp 我还是在 SignalR 的源码里翻出来的 (
    不过后来我就直接用 ws 了
    coder001
        62
    coder001  
       311 天前 via Android
    @liuhan907 能用 ws 是我的梦想,一直在做梦,苦于设备目前只支持 TCP 接入
    如果走 ws 就不需要专门开一种 TCP 服务端了,做好高可用使劲加 Web 服务器就成)
    coder001
        63
    coder001  
       311 天前
    @liuhan907

    另外,我看 Kestrel 源代码时注意到监听是单线程异步,这可能会 accept 不过来,经验告诉我如果几万 TCP 同时打进去,能进去的可能会只有几千个

    https://github.com/dotnet/aspnetcore/blob/main/src/Servers/Kestrel/Transport.Sockets/src/SocketConnectionListener.cs#LL67C64-L67C64
    liuhan907
        64
    liuhan907  
       310 天前
    @coder001
    以我对 IOCP 的认知,Windows 上应该不会发生这个问题。因为 Accept 慢主要是慢在创建 Socket 上,而 IOCP 创建是系统内核在处理这个问题,不会拖慢应用。
    至于 Linux 上,鉴于我对 epoll 的熟悉程度不如 IOCP ,所以我不是很确定。但是曾经读过 devblog 的文章,里面表示 Linux 上的实现是 epoll + 线程池,所以我觉得可能也没有你担心的问题,可能。
    coder001
        65
    coder001  
       303 天前
    @liuhan907
    压测了一下 Kestrel 的 TCP 服务端,花了几秒钟来 accept 两万 TCP ,虽然有部分重连,但还是全都连上了

    看来以后可以用它,妈妈再也不用担心我维护不好 Socket 和 SAE 了,乐。
    BifroMQ
        66
    BifroMQ  
       303 天前
    熟悉哪个选哪个。
    不用担心,99.99%情况下, 语言不会成为瓶颈;
    0.01%情况下业务增长到那个程度早重构了。
    liuhan907
        67
    liuhan907  
       303 天前
    @coder001
    说不定你再改改配置和 GC 选项,连重连都没了(
    coder001
        68
    coder001  
       272 天前 via Android
    @liuhan907 回来报喜
    正经项目换 kestrel 重构之后,目前压测连接承载能力摸到 3 万了,需要花一点时间来 accept ,问题不大~
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2912 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 07:49 · PVG 15:49 · LAX 00:49 · JFK 03:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.