关于 Java 和 go 高并发的话题

2021-07-22 22:45:05 +08:00
 MakHoCheung
go 因为有协程,所以高并发是它的一大优势,但是我看博客,别人说 groutine 的底层也是线程池,这样跟 Java 也一样,为什么 go 在高并发这块就很厉害呢(我不知道 Java 在高并发这块是不是比 go 弱,我没做过什么高并发项目)。发散一下就是 Java 的 NIO +线程池(现实例子就是 netty )跟 go 在高并发这块差距是不是巨大?
6980 次点击
所在节点    问与答
93 条回复
gollwang
2021-07-23 14:12:24 +08:00
打个比方:Java 的多线程就有点类似于,我要找 10 个人去干 10 件事,每个人干一件刚刚好
golang 的协程呢,10 个人我可以干 10 件事,也可以干 100 件事,因为当有人干某一件事发生了阻塞,他可以再干其他的事。
所以就会出现一种情况,当人数是相当的,比如:都是 10 个人,要干的事情是一定的,比如要干 100 件事,但是事情的复杂度不是一样的,那么对应 Java 来说可能就是 10 个人每人干 10 件,时间和工作量调度可能就不是均衡的,对于 go 来说,我 10 个人就不断干事情,可能有的人干的数量多,有的人干的数量少,但是我们的工作量相对来说是均衡的,因为有可能我干一件事,你要干几件事。

我不知道这样说对不对,纯属个人理解,大佬们别喷
php01
2021-07-23 14:22:53 +08:00
GOLANG 中,P 列表和 M 相绑定,极大减少了协程切换带来的系统调用。这就是差距,如果说的不对请大佬们指出。
MakHoCheung
2021-07-23 14:23:14 +08:00
@gollwang Java 的 forkjoin 框架就有工作窃取,一个线程干完可以干另外一个线程剩下的活
honkki
2021-07-23 14:44:33 +08:00
没有线程频繁的上下文切换、GMP 一个线程管理多个 goroutine 、goroutine 是可伸缩的栈内存大小
ylsc633
2021-07-23 14:48:14 +08:00
Carlgao
2021-07-23 15:54:37 +08:00
说一段我的理解:
go 的线程会预先创建一批线程,真正执行的线程对应 CPU 数量,每个执行线程都有一个任务队列,没有多线程同时取任务加锁的问题。
当执行线程阻塞时会从睡眠线程中唤醒一个与原任务队列绑定,这点类似于线程池。
如果没有阻塞一个任务执行完之后切换下一个就行了,这样避免了线程上下文切换。
kksco
2021-07-23 16:09:06 +08:00
一言以蔽之,golang 的 runtime 在 os 下面又实现了一套自己的规则,好处就是吹得比较多的代码并发无脑写,同步的写法确实心智负担低,开多个 goroutine 没啥压力。缺点也有,c/c++ 大佬想掌控一切的路就被 runtime 堵死了,比如像 nginx 这种亲核性就没办法实现。
Jooooooooo
2021-07-23 16:11:00 +08:00
你用 netty 就好了.
lesismal
2021-07-23 16:14:23 +08:00
@x940727
"不是 java 不异步性能差"
——这是最基础的错误认知,所有语言都做不到同步还性能强的(这里的同步是指 fd 阻塞 io,不是指接口同步,go 标准库是 fd 非阻塞但接口同步的),因为同步意味着进程 /线程占用,而进程 /线程数量有限,你 fd 阻塞 io 随便就让线程池都在那等来等去的,处理频率大大降低。所以单比性能的时候不只是以前 c/c++吊打 java 阻塞 io 的框架,连 nodejs 都吊打。
既然知道 netty 强,你就应该了解为啥强,如果不异步还能高并发高性能,那 erlang/golang 之外的语言还搞异步出来干嘛?


"如果单论语言性能,Java 是要强于 Go 的。"
——醒醒。不同消耗对应的指令性能,java 和 go 各有千秋,但是整体算下来,java 并不比 go 强。
lesismal
2021-07-23 16:20:31 +08:00
@kksco
"缺点也有,c/c++ 大佬想掌控一切的路就被 runtime 堵死了,比如像 nginx 这种亲核性就没办法实现。"
——我这搞了一份 poller 的,协成、线程数量仍然可控,业务协程数量可控并且可以做到业务代码同步、网络层异步、性能、内存各方面的平衡:
github.com/lesismal/nbio

只是:go 的指令、runtime 、gc 这些,确实让 go 性能比 c/c++还差很多

更多细节有在另一个异步库 gev issue 中做更多的阐述:
github.com/Allenxuxu/gev/issues/4
x940727
2021-07-23 17:13:00 +08:00
@lesismal 嗯。Java 不比 Go 强……我就只问你一个问题,如果是现在那些互联网项目,高并发,高吞吐量的场景下,Go 的 GC 表现怎么样?和 JVM 比?为什么头条现在也在大规模的招聘 Java 的程序员?为什么不继续用 Go ?说白了 Go 的适用场景还是在那些要求低延时,低吞吐量的基础建设场景,真去抗大规模流量和 Java 比就差远了(有时间优化的另说,类似 Facebook 的 PHP hhvm )。
x940727
2021-07-23 17:15:41 +08:00
@lesismal Java Servlet 同步性能依旧不好的原因就是因为在对象的生命周期中做了太多的事情,不然并不会比那些很快的同步 Web 框架差多少的。 [普通并发量 go 还是有优势,写起来简单,不容易写出瓶颈,java 如果不异步性能太差,netty 了又 callback hell] 这句话是你说的,你说人家最基础的错误认知?
MakHoCheung
2021-07-23 17:18:04 +08:00
@x940727 头条什么时候开始找 Java 了?我问字节的朋友招不招 Java,他都说字节不招 Java
lesismal
2021-07-23 18:07:59 +08:00
@x940727 go 的 gc 整体表现还真是比 java 强,而且特定业务或者框架用 pool 优化,内存、gc 更优。我自己那个库,就用了大量的 pool 优化。我们很多项目也是很多语言,对比 java 和 go 的项目,go 内存、cpu 占用各项指标都吊打 java 。

"为什么头条现在也在大规模的招聘 Java 的程序员?"
——兄弟,分析问题要学会逻辑理清晰一点。大规模招聘 java 不等于不继续用 go,完全没有证据表明字节没有继续大量用 go 。而招聘这个主要涉及几个方面,一是业务线,比如偏向电商、后台、企业级等 java 已经有成熟的社区积累的,市场上也有大量的该领域的 java 从业者,反观 go,一共才诞生了多少年,社区和从业者数量没得比,字节这种业务扩张猛的,想大量招 go 的人都招不到,然后优势 java 成熟领域,何必招 go ?反而是性能敏感的领域,比如中间件、云服务这些各种基础设施,你看有几个用 java 做的?包括比如以前 ELK,现在都变成 EFK 了,为啥?你 java 的 logstash 太渣了啊!而且这还只是 go 出生太晚,如果跟 java 同时代出生,怕是没 java 啥事了,很多 appache 顶级项目怕是会用 go 实现了

"Java Servlet 同步性能依旧不好的原因就是因为在对象的生命周期中做了太多的事情"
——我不了解 java servlet,但是你们之前提到他是非异步的。如果你们确定他是同步的、阻塞 fd,那这太基础了,阻塞 fd 对线程资源的浪费肯定是影响响应的最大因素(除非你故意写对象生命周期巨大消耗的示例、让对象生命周期这些的影响超过阻塞 fd 的影响)。
lesismal
2021-07-23 18:09:43 +08:00
@x940727

[普通并发量 go 还是有优势,写起来简单,不容易写出瓶颈,java 如果不异步性能太差,netty 了又 callback hell]
——java 我肯定是不熟,但是 netty 异步 callback 应该没问题吧?我前面这句话有什么问题的话,请你指正。
lesismal
2021-07-23 18:15:00 +08:00
@x940727

"不然并不会比那些很快的同步 Web 框架差多少的"
——这里提到的 "那些很快的同步 Web 框架" 是指哪些框架?恕我见识少,还没听说过有高性能的同步框架(跟之前提到的一样,这里的同步是指同步 IO,不是指 erlang/golang 这种语言级同步)
lesismal
2021-07-23 18:24:43 +08:00
@x940727 同步 io 与异步 io 什么区别? select 跟 epoll 什么区别? java 同步库跟 NIO/Netty 什么区别?互联网最早期时进程池模型线程池模型就是同步 io,为什么后来又要搞异步框架?异步 io 你有深入了解过吗?读相关的书或者看优秀项目源码甚至自己手撸过吗? CSAPP,APUE,UNP,内核相关的书,java 高并发网络相关的书,或者其他的优秀的系统层网络层优秀的书有真正认真读过并且理解了吗?
至少从前面几楼你的一些措辞,确实是基础认知的欠缺,如果没有花很多时间在我提问的这些上,建议多研究下,可以等先去确认下自己搞懂了再说
BBCCBB
2021-07-23 19:32:03 +08:00
java 里查数据库不一定要用 jdbc, 比如 vertx 里就是自己封装的. 还有 r2dbc 这种, 数据库官方都在支持..

不过没有语言级别的支持.

只是用 reactor 或者回调的化还是不够友好.
x940727
2021-07-23 20:11:35 +08:00
@MakHoCheung 招的 2B 业务很多很多都是 Java 的,我认识一个人就是在字节写 Java 。
@lesismal 不了解就是 Go 的 GC 整体比 Java 强? OMG,什么时候 Go 的 GC 能打得过 JVM 的 GC 了,我一个 Java 菜鸡瑟瑟发抖……不谈了,Go 宇宙第一好么。还有 ELK 这个事情,你知道 ElasticSearch 就是 Java 写的吗?还有为什么变成 EFK 了,人家 elastic 推荐的是 ELKF,filebeat 就专门拿来读取文件,logstash 提供 grok 啥的,在你眼里反正 Java 就是不行,我也没办法劝服你,Java 就是弱鸡好吧……
x940727
2021-07-23 20:32:45 +08:00
@lesismal #57 我不知道你这个蜜汁自信从哪里来的,你问的这些问题,你是面试八股文背多了吗?
这些基础的东西有什么好在这里逼叨叨的,就你看过 CSAPP ?还有你自己说不清楚 Java,然后在这里指点 Java 的江山?不好意思,我看过 CSAPP,也看过 MIT 6.824,CMU 15-213,还有现代操作系统这些的,至于 Java 的并发书籍,我看过火车头,JVM 的我看过 Oracle Java 虚拟机规范的和周志明写的深入理解 Java 虚拟机,二三版都看过。
我建议你少在这里背八股文,你自己说的 [java 如果不异步性能太差] 事实就是 Java 的语言性能已经是目前来说所有语言里面排得上前列的了,不然那么多顶级工程师优化 JVM 不是白优化了吗?
还有你说的 [netty 了又 callback hell] 这个大把最佳实践教你消除回调地狱,你自己不了解就别说 netty 就一定会有这种模式。
还有 Web 框架的性能排名 https://www.techempower.com/benchmarks/#section=data-r20&hw=ph&test=composite 你可以在这个页面里面自己看,Java 的异步框架的排名是非常靠前的,我说 Servlet 慢就是因为。

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

https://www.v2ex.com/t/791169

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

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

© 2021 V2EX