说说这篇「我为啥从python转向go」

恩看了这篇自己怎么从python转向go,看来作者也是
KSO
轻办公/集团快盘团队的。作为快盘从无到有一代的工程师之一(总是被潇洒哥说他们改我留下的
bug ),又恰好是 Python/Go 双修(大雾其实自己是 Rust
党),其实一初叶自己是不容的,duang duang duang,这就随手写一些把。

一段段来吧,首先作者说 Python 是动态语言

python是一门动态语言,不是强类型系统。对于一个变量,我们有时候压根不知晓它是何等类型,然后就可能出现int

  • string这样的运作时不当。

在python里面,可以允许同名函数的面世,后一个函数会覆盖前一个函数,有两次咱们系统一个很惨重的谬误就是因为那多少个导致的。

实在,假使是静态检查,pylint 和 pyflakes 是足以做这件事的,尽管无法和
go
这种静态编译型语言比,但也充分了。假如没记错的话,阿通当年是讲求全组都在付出前做静态检查的。我觉着这种问题更多的应有是人士素质上来制止,毕竟葱头也说过,代码自己写的就要多回头看看,看能不可以重构,能不可能做更好。不是说偷懒不行,但是从中得出
Python 动态特性太灵活,Python:怪我咯?

此外,函数作为第一对象,在 Python 中是 feature,Go 要写个
mock,简直虐得不要不要的。

实质上这么些一贯是成百上千人吐槽python的地点,不过想想,python最起先是为了缓解什么问题而被支付出来的?我们就是要将他用到高性能服务器开发方面,其实也是有点难为它。

倘若没记错,无论是轻办公或者快盘,是重 IO 不重
CPU,最大耗时是数码块加密这块,我在的时候是 Java
写的。另外高性能服务器选 Go 也是虐得不要不要的,各个小心翼翼避免GC。大多数无限气象下,pypy 的性质足矣胜任了,我认为这不算丰裕规范。

python的GIL导致导致力不从心真正的多线程,我们也许会说自己用多进程不就完了。但假设局部划算需要涉及到多进程并行,进程之间的报道支出也是不得不考虑的。

其实,Python 有宏可以绕开这么些GIL,但是呢架构设计得好其实能够防止的,到异步这块我会说。

无状态的分布式处理利用多进程很有利,譬如处理http请求,咱们就是在nginx前边挂载了200四个django
server来处理http的,但这样五个过程自然导致全部机器负载偏高。

但哪怕我们利用了五个django进程来拍卖http请求,对于部分超大量请求,python如故处理不东山再起。所以我们运用openresty,将高频次的http请求使用lua来促成。可这般又导致使用二种开发语言,而且一些逻辑还得写两份不同的代码。

一经猜想没错,你们现在还在用五年前写的 Gateway?这么些基于 django route
的流量分发层?四年前自己离开的时候已经小范围的运用 Flask+Gevent Demo
测试过了,无论是性能依旧负载都比同步模型的 django 有优势。假如还是django
这套的话,我只得说相比遗憾,毕竟这时候金山新员工大赛头牌就是自家和多少个小伙伴写的实时同步在线文档编辑系统,用的就是这套技术。

据此那是个工程问题,并非语言问题。 Python
提供给了你了这样多工具,硬要选一个传统的,Old fashion
的,Python:怪我咯?

django的网络是联名阻塞的,也就是说,如果我们需要拜访外部的一个劳动,在等候结果回到这段时日,django无法处理任何其他的逻辑(当然,多线程的除了)。假使访问外部服务需要很长日子,这就表示我们的整整服务几乎在很长一段时间完全不可用。

为领悟决这一个题材,我们只好不断的多开django进程,同时需要确保所有服务都能迅速的拍卖响应,但思维这实质上是一件很不靠谱的政工。

一道模型并非不行,因为 overhead
丰裕低,很多工作场景下用同步模型反而会博得更好的职能,比如豆瓣。同步模型最大的题材是对此
IO 密集型业务等待时间充足长,这时候需要的不是换语言
,而是提示您是不是架设要改一下了。

即便如此tornado是异步的,不过python的mysql库都不辅助异步,这也就象征一旦我们在tornado里面访问数据库,大家依旧可能面临因为数据库问题造成的总体服务不可用。

tornado 是有那一个题材,可是 gevent 已经解决了。我在 node.js
的某问题下一度回答过,对于 node 而言,能选拔的异步模型只有一个,而
Python 就是太多采用了。另外 pypy+tornado+redis
可以随意虐各样长连接的场所,比如我给我厂写过的一个 push service。

骨子里异步模型最大的问题在于代码逻辑的隔离,因为是事件触发的,所以我们都是经过callback举行有关处理,于是代码里面就平时出现干一件事情,传一个callback,然后callback里面又传callback的场所,这样的结果就是总体代码逻辑异常混乱。

以此还真不是,假使说没有 ES6 的 JavaScript,可能真有 Callback
hell,但这是 Python 啊!Python 早就实现了左值绑定唉,yield
这架式比某些时刻吹的言语不通晓高到什么地方去了,当然我说的是完整版的 Python3
yield。即便是不完整的 Python 2 yield
用来异步表明式求值也是完全够用的,tornado 的 gen.coroutine 啊。

一块形态写异步,在 Python
实力强的营业所内部早普及了,这是个工程问题,并非语言问题。当然把这种事怪在
Python 身上,Python:怪我咯?

python没有原生的协程帮助,尽管能够透过gevent,greenlet这种的上patch形式来支撑协程,但说到底更改了python源码。另外,python的yield也足以开展简短的协程模拟,但究竟无法跨堆栈,局限性很大,不知情3.x的本子有没有改正。

无论是 Gevent 仍旧 格林let 均没修改 Python 源码,事实上那货已经化为了
Py2 coroutine
的规范,加上豆瓣开源出来的greenify,基本上所有的库都可以平滑的异步化,包括
MySQL 等 C 一流的 lib。自从用上这套技术后,豆瓣的 Python dev
各样爽得不要不要的。

当我首先次拔取python开发项目,我是没成功安装上项目需要的包的,光安装成功mysql库就弄了很久。后来,是一位同事将他一切python目录打包给我用,我才能正常的将品种跑起来。话说,现在有了docker,是何等令人幸福的一件事情。

而部署python服务的时候,我们需要在服务器下面安装一堆的包,光是这点就令人很勤奋,即使可以透过puppet,salt这个自动化工具解决部署问题,但比较而言,静态编译语言只用扔一个二进制文件,可就便宜太多了。

正要我又是在开发基于 docker 的阳台, docker
还真不是用来做安排这事的。首先, Python 是有 virtualenv
这一个工具的,事实上相比包管理和包隔离,Python 比 Go
高得不知道什么地方去了。Python 跟 Git 谈笑风生的时候, Go 的 dev
们还得考虑自身怎么着才能使得 import
的包稳定在一个版本上(当然现在有成千上万第三方方案)。Virtualenv + Pip
完全可以兑现 Python
部署自动化,所以这多少个问题自己觉着是,工具链选用问题。毕竟是个十几年的老妖怪了,Python
啥情况没见过呀,各个包裹工具任君采纳,强行说 Python
部署不便民,Python:怪我咯?

python异常灵活简单,写c几十行代码才能搞定的效用,python一行代码没准就能化解。不过太简单,反而造成成千上万同桌无法对代码进行深层次的构思,对全体架构进行周详的考量。来了一个要求,啪啪啪,键盘敲完开速实现,结果就是代码越来越混乱,最后造成了一切项目代码失控。

已经虎扑有个帖子问 Python
会不会下跌程序员编程能力
,我只可以说这着实很人有关。你不去考虑深层次的事物怪语言十分是没道理的,这好,Go
里面 goroutine 是怎么落实的,一个带 socket 的 goroutine
最小能不负众望多少内存,思考过?任何语言都有协调的优势和劣势,都需要执行者自己去看清,一味的以为简单就不会深深思考这是有题目标。其余,代码混乱我觉着依旧工程上的控制力不够,豆瓣有超越10W行的
Python 实现,即便不说很圆满,大体上完成了不会混杂这么个目的。

还有,C 写几十行搞定的 Python 一行解决这纯属是重点
feature,生产力啊,人士安排啊,招人培育的资本啊,从工程上来说,Python
在这一块完全是加分项,不是各样门类都务求最好的面世,极致的频率,做工程很多时候都是要取舍的。

即便java和php都是最好的编程语言(我们都这么争的),但自我更倾向一门更简短的语言。而openresty,尽管性能强悍,但lua依旧是动态语言,也会遇到前面说的动态语言一些问题。最终,前金山许式伟用的go,前快盘架构师葱头也用的go,所以咱们很当然地拔取了go。

Openresty 用 lua
如若按照动态语言的角度去看,还真算不上,顶多是个大概点的
C。许式伟走的时候大多数都是
CPP,葱头近期自我还不知道她创业用的是何许写的,可是她迟早没言语倾向。当年无论是
leo 依然 ufa,一个用 Python 一个用 Java,
他都是从工程实际来摘取选用什么的言语。

error,好吧,假诺有语言洁癖的同校可能确实受不了go的语法,尤其是预约的末梢一个再次来到值是error。

这实际是 Go style,无论是 go fmt 依然 error style,Go
其实是想抹平不同工程师之间的品格问题。不再为了一个缩进和大括号地点怎么的浪费时间。这种艺术并不是不佳,只是我个人认为没
rust 这种再次来到值处理友善。

GC,java的GC发展20年了,go才这样点时间,gc铁定不圆满。所以大家照例无法随便的写代码,不然在大请求量上边gc可能会卡顿整个服务。所以有时,该用对象池,内存池的肯定要用,即使代码丑了点,但好歹性能上去了。

1.4 开首 go 就是 100% 精确 GC
了,此外说到卡顿啊,完全和您怎么用对象有关,能内联绝不传引用大部分情景是一心够用的,这样
gc 的震慑程度会压低。实在想用池……只可以说为何不选 Java。

先天性的并行协助,因为goroutine以及channel,用go写分布式应用,写并发程序异常的容易。没有了蛋疼的callback导致的代码逻辑割裂,代码逻辑都是各类的。

Java,这是有代价的,goroutine
的内存消耗总结(当然1.3依旧1.4初阶得到了很大的立异,内存最小值限制已经没了),channel
跨线程带来的性质损耗(跨线程锁),还有对 goroutine 的控制力几乎为 0
等。综上说述这种嘛,算不上是杀手级特性,我们都有,是惠及了某些,但也有投机的弊病。比如大家用
go 吧,平日就相比蛋疼 spawn 出去的 goroutine 怎么漂亮的
shutdown,反而有时候把业务做复杂化了。

性能,go的性质可能赶不上c,c++以及openresty,但的确也挺强悍的。在我们的序列中,现在单机就布局了一个go的经过,就完全可以胜任往日200个python进程干的政工,而且CPU和MEM占用更低。

自家不谨慎的实测大概 gevent+py2 能落得相同逻辑 go 实现的
30%~40%,pypy+tornado 能达到
80%~90%,混合了有些乘除和连接处理什么的。重要依然看事情场景吧,纯粹的
CPU bound 当然是 go 好,纯粹的 IO bound 你即便用 C 也没用啊。

运维部署,直接编译成二进制,扔到服务器上边就成,比python需要设置一堆的条件这是简简单单的太多了。当然,虽然有cgo,我们也需要将相应的动态库给扔过去。

俺们明天基于 glibc 所处的 host
版本不同有2套编译环境,看上去是部署简单了,编译起来坑死你。另外即便说
disk 便宜,这几行代码就几M了,集群同步部署耗时在某些情状下还真会出篓子。

支付效率,即使go是静态语言,但我个人感觉开发效率确实挺高,直觉下面跟python连镳并轸。对于自身个人来说,最好的例证就是我用go快速支付了非凡多的开源组件,譬如ledisdb,go-mysql等,而那几个最先河的本子都是在很短的刻钟里面完成的。对于我们项目以来,我们也是用go在一个月就重构完成了第一个版本,并发布。

go 的支出功用高是比较 C,比较 python,大概后者只需要3天呢……

总的说来,Go 不是不好,Python
也不是分外,做工程嘛,无外乎就是考虑资金,时间成本,人力成本,维护成本等等。
Go 和 Python 互有千秋,就看取舍了。当然一定要说 Python
不行,Python:怪我咯?

相关文章