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

2023-06-14 14:22:47 +08:00
 unt
设备量:10W 台同时在线,同时收发
对接方式:mqtt,tcp ,websocket (设备种类较多,每种设备不同的对接协议)
公司背景:中型企业,toB,本公司说了算,出现 bug 也没事
6567 次点击
所在节点    程序员
68 条回复
ychost
2023-06-15 11:37:58 +08:00
性能这些语言都不在话下,主要看哪个出问题了能修问题
yazinnnn
2023-06-15 11:39:55 +08:00
@hhjswf 大多数 spring boy 写不了 netty
coder001
2023-06-15 11:44:58 +08:00
@liuhan907 #28

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

这算 CPU 密集吗🤔 (不过这倒是和主题的物联网沾上边了
WispZhan
2023-06-15 12:50:25 +08:00
中间件用 go ,平台化业务用 Java
ssr 和 bff 用 node

好全用上了🐶
INCerry
2023-06-15 13:29:04 +08:00
@coder001

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

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

目前用若干个绑定了队列的线程,每次有回调就挑队列长度最短的分配工作项,压测看起来数据没这么难看了
压测用 5 万个 TCP 同时打进去,PPS 没测量,几乎所有 PDU 都小于 1400 ,姑且按 PDU 计算的话,极端状况下往返加起来可能会达到( x4 ) 20 万 PDU 每秒。
协议超时时间是 30 秒,但超过 10 秒就会被称为数据不好看
liuhan907
2023-06-16 15:18:40 +08:00
@coder001
怎么说呢,只有 5W 连接的情况下这个数据感觉有点奇怪。你的原始测试代码还有留存么?
coder001
2023-06-16 15:21:53 +08:00
@liuhan907
目前性能数据已经可以接受,就不放出来丢人现眼了 _(:з)∠)_
liuhan907
2023-06-16 15:53:22 +08:00
@coder001
我只是好奇为什么数据会这么差,因为和我之前压测的数据比差的不少。
学习一下,以后避坑(
coder001
2023-06-16 16:59:52 +08:00
@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
2023-06-16 17:18:27 +08:00
@coder001
搞明白了。Select 这个就不多说效率没眼看。至于 SAE 那个确实是专用 IO 线程更好。
我建议你看一下 asp.net core 现在使用的那个抽象模式以及实现。我认为应该是目前比较好的答案了。
主要代码在 aspnetcore 项目 src\Servers\Kestrel\Transport.Sockets\src 下面。
BBCCBB
2023-06-17 21:41:35 +08:00
我看大家都在说并发用 go 的协程.. 其实 go 的协程在 socket 量级 10w 这种, 如果你每个 socket 都开 2 个 goroutine, 20w 个协程, go 的调度压力很大的, 这种情况下不太适合有栈协程, 所以你看 go 里也有许多框架封装后就是 netty 的线程模型的样子. 几个 goroutine 就能处理所有 socket 的 IO.

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


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

https://github.com/davidfowl/MultiProtocolAspNetCore/tree/master/KestrelTcpDemo

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://yangjunhui.monster/t/948663

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX