恩看了这篇我为什么从python转向go, 看来作者也是 KSO 轻办公/企业快盘团队的。作为快盘从无到有时期的工程师之一(总是被潇洒哥说他们改我留下的 bug ),又恰好是 Python/Go 双修(大雾其实我是 Rust 党),其实一开始我是拒绝的,duang duang duang,那就随手写一点把。 一段段来吧,首先作者说 Python 是动态语言
事实上,如果是静态检查,pylint 和 pyflakes 是可以做这件事的,虽然不能和 go 那种静态编译型语言比,但也足够了。如果没记错的话,阿通当年是要求全组都在提交前做静态检查的。我认为这种问题更多的应该是人员素质上来避免,毕竟葱头 也说过,代码自己写的就要多回头看看,看能不能重构,能不能做更好。不是说偷懒不行,但是从中得出 Python 动态特性太灵活,Python:怪我咯? 另外,函数作为第一对象,在 Python 中是 feature,Go 要写个 mock,简直虐得不要不要的。
如果没记错,无论是轻办公还是快盘,是重 IO 不重 CPU,最大耗时是数据块加密那块,我在的时候是 Java 写的。另外高性能服务器选 Go 也是虐得不要不要的,各种小心翼翼避免 GC。大多数极端情况下,pypy 的性能足矣胜任了,我认为这不算充分条件。
其实,Python 有宏可以绕开这个 GIL,但是呢架构设计得好其实可以避免的,到异步那块我会说。
如果推测没错,你们现在还在用五年前写的 Gateway?那个基于 django route 的流量分发层?四年前我离开的时候已经小范围的使用 Flask+Gevent Demo 测试过了,无论是性能还是负载都比同步模型的 django 有优势。如果还是 django 这套的话,我只能说比较遗憾,毕竟当年金山新员工大赛头牌就是我和几个小伙伴写的实时同步在线文档编辑系统,用的就是这套技术。 因此这是个工程问题,并非语言问题。 Python 提供给了你了这么多工具,硬要选一个传统的,Old fashion 的,Python:怪我咯?
同步模型并非不行,因为 overhead 足够低,很多业务场景下用同步模型反而会取得更好的效果,比如豆瓣。同步模型最大的问题是对于 IO 密集型业务等待时间足够长,这时候需要的不是换语言 ,而是提醒你是不是架构要改一下了。
tornado 是有这个问题,但是 gevent 已经解决了。我在 node.js 的某问题下曾经回答过,对于 node 而言,能选择的异步模型只有一个,而 Python 就是太多选择了。另外 pypy+tornado+redis 可以随意虐各种长连接的场景,比如我给我厂写过的一个 push service。
这个还真不是,如果说没有 ES6 的 JavaScript,可能真有 Callback hell,但这是 Python 啊!Python 早就实现了左值绑定唉,yield 那姿势比某些天天吹的语言不知道高到哪里去了,当然我说的是完整版的 Python3 yield。即便是不完整的 Python 2 yield 用于异步表达式求值也是完全足够的,tornado 的 gen.coroutine 啊。 同步形态写异步,在 Python 实力强的公司里面早普及了,这是个工程问题,并非语言问题。当然把这种事怪在 Python 身上,Python:怪我咯?
无论是 Gevent 还是 Greenlet 均没修改 Python 源码,事实上这货已经成为了 Py2 coroutine 的标准,加上豆瓣开源出来的greenify,基本上所有的库都可以平滑的异步化,包括 MySQL 等 C 一级的 lib。自从用上这套技术后,豆瓣的 Python dev 各种爽得不要不要的。
恰好我又是在开发基于 docker 的平台, docker 还真不是用来做部署这事的。首先, Python 是有 virtualenv 这个工具的,事实上对比包管理和包隔离,Python 比 Go 高得不知道哪里去了。Python 跟 Git 谈笑风生的时候, Go 的 dev 们还得考虑我怎样才能使得 import 的包稳定在一个版本上(当然现在有很多第三方方案)。Virtualenv + Pip 完全可以实现 Python 部署自动化,所以这个问题我认为是,工具链选取问题。毕竟是个十几年的老妖怪了,Python 啥情况没见过啊,各种打包工具任君选择,强行说 Python 部署不方便,Python:怪我咯?
曾经知乎有个帖子问 Python 会不会降低程序员编程能力, 我只能说这真的很人有关。你不去思考深层次的东西怪语言不行是没道理的,那好,Go 里面 goroutine 是怎么实现的,一个带 socket 的 goroutine 最小能做到多少内存,思考过?任何语言都有自己的优势和劣势,都需要执行者自己去判断,一味的觉得简单就不会深入思考这是有问题的。另外,代码混乱我认为 还是工程上的控制力不够,豆瓣有超过10W行的 Python 实现,虽然不说很完美,大体上做到了不会混乱这么个目标。 还有,C 写几十行搞定的 Python 一行解决这绝对是重大 feature,生产力啊,人员配置啊,招人培养的成本啊,从工程上来说,Python 在这一块完全是加分项,不是每个项目都要求极致的并发,极致的效率,做工程很多时候都是要取舍的。
Openresty 用 lua 如果按照动态语言的角度去看,还真算不上,顶多是个简单点的 C。许式伟走的时候大多数都是 CPP,葱头目前我还不知道他创业用的是什么写的,不过他肯定没语言倾向。当年无论是 leo 还是 ufa,一个用 Python 一个用 Java, 他都是从工程实际来选择使用什么样的语言。
这其实是 Go style,无论是 go fmt 还是 error style,Go 其实是想抹平不同工程师之间的风格问题。不再为了一个缩进和大括号位置什么的浪费时间。这种方法并不是不好,只是我个人觉得没 rust 那种返回值处理友善。
1.4 开始 go 就是 100% 精确 GC 了,另外说到卡顿啊,完全和你怎么用对象有关,能内联绝不传引用大部分场景是完全足够的,这样 gc 的影响程度会最低。实在想用池……只能说为啥不选 Java。
这是有代价的,goroutine 的内存消耗计算(当然1.3还是1.4开始得到了很大的改善,内存最小值限制已经没了),channel 跨线程带来的性能损耗(跨线程锁),还有对 goroutine 的控制力几乎为 0 等。总之这种嘛,算不上是杀手级特性,大家都有,是方便了一点,但也有自己的弊端。比如我们用 go 吧,经常就比较蛋疼 spawn 出去的 goroutine 怎么优美的 shutdown,反而有时候把事情做复杂化了。
我不严谨的实测大概 gevent+py2 能达到同样逻辑 go 实现的 30%~40%,pypy+tornado 能达到 80%~90%,混合了一些计算和连接处理什么的。主要还是看业务场景吧,纯粹的 CPU bound 当然是 go 好,纯粹的 IO bound 你就是用 C 也没用啊。
我们现在根据 glibc 所处的 host 版本不同有2套编译环境,看上去是部署简单了,编译起来坑死你。另外虽然说 disk 便宜,这几行代码就几M了,集群同步部署耗时在某些情况下还真会出篓子。
go 的开发效率高是对比 C,对比 python,大概后者只需要3天吧…… 总之,Go 不是不好,Python 也不是不行,做工程嘛,无外乎就是考虑成本,时间成本,人力成本,维护成本等等。 Go 和 Python 互有千秋,就看取舍了。当然一定要说 Python 不行,Python:怪我咯? |