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

图片 1

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

docker

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

正文的配置环境是Ubuntu 14.04

python是一门动态语言,不是强类型系统。对于一个变量,我们有时压根不驾驭它是哪些项目,然后就可能出现int

  • string这样的运转时不当。

在python里面,可以允许同名函数的产出,后一个函数会覆盖前一个函数,有五回我们系统一个很严重的错误就是因为这么些导致的。

  • Docker

实质上,尽管是静态检查,pylint 和 pyflakes 是可以做这件事的,即便不可以和
go
这种静态编译型语言比,但也丰裕了。尽管没记错的话,阿通当年是讲求全组都在交付前做静态检查的。我觉得那种题材更多的相应是人士素质上来避免,毕竟葱头也说过,代码自己写的即将多回头看看,看能不可能重构,能不可能做更好。不是说偷懒不行,可是从中得出
Python 动态特性太灵敏,Python:怪我咯?

Docker
详细概念可以去search,简单的话就是把利用打包到一个容器里的轻量级系统虚拟化服务

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

  • IPython Notebook

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

IPython Notebook
既是一个交互总括平台,又是一个记下总括过程的「台式机」。它由服务端和客户端两有的组成,其中服务端负责代码的表达与计算,而客户端负责与用户展开相互。
服务端能够运作在本机也得以运行在中距离服务器,包含负责运算的 IPython
kernel (与 QT Console 的 kernel 相同) 以及一个 HTTP/S 服务器
(Tornado)。
而客户端则是一个针对服务端地址的浏览器页面,负责接受用户的输入并承担渲染输出。

假设没记错,无论是轻办公或者快盘,是重 IO 不重
CPU,最大耗时是多少块加密这块,我在的时候是 Java
写的。另外高性能服务器选 Go 也是虐得不要不要的,各个小心翼翼制止GC。大多数极致情形下,pypy 的习性足矣胜任了,我觉着这不算充分规范。

正文重要记录使用Docker 在服务器部署IPython Note
应用的经过。比传统的配置方案果然简单轻松不少。

python的GIL导致导致不能真正的多线程,我们莫不会说自己用多进程不就完了。但如果部分乘除需要涉及到多进程并行,进程之间的简报支出也是只可以考虑的。

知识点

  1. Docker 的基本概念
  2. 部署IPython 容器
  3. 应用Nginx 容器反向代理IPython

实际上,Python 有宏可以绕开这多少个GIL,可是呢架构设计得好其实可以避免的,到异步这块我会说。

Docker 的基本概念

下文的操作重要涉及Docker的瞬间多少个知识点:

  • Docker 的镜像(image)、容器(container)、仓库(registerie)
  • Docker 的安装
  • Docker 的底子用法
  • Docker的端口映射
  • Docker 数据卷
  • 链接容器

详见的消息可以自动检索

无状态的分布式处理利用多进程很便宜,譬如处理http请求,大家就是在nginx前边挂载了200两个django
server来处理http的,但如此三个过程自然导致全部机器负载偏高。

但即便大家使用了五个django进程来处理http请求,对于有些超大量请求,python如故处理不过来。所以我们选用openresty,将高频次的http请求使用lua来兑现。可这么又导致使用三种开发语言,而且有些逻辑还得写两份不同的代码。

部署IPython

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

下载IPython 的镜像

官方Docker镜像地址,里面包含5个镜像:

  • notebook
  • ipython
  • scipyserver
  • scipystack
  • nbvierer

总而言之说一下这多少个镜像的界别 ipython
是以上多少个镜像的一块儿的根镜像。notebook
提供了一个web的前端。scipystackipython的底子上设置了诸多科学统计的包(cython,h5py,matplotlib,numpy,pandas,patsy,scikit-learn,scipy,seaborn,sympy,yt),而scipyserver则在scipystack的根基上提供了web的前端。nbviewer则是nbviewer.ipython.org的实现
更多详细信息请到GitHub上的docker-notebook
查看
选择scipystack镜像最简便易行,可是急需下载的事物也越多。下文采取的也是scipystack

$ sudo docker pull ipython/scipyserver

从而那是个工程问题,并非语言问题。 Python
提供给了您了这般多工具,硬要选一个观念的,Old fashion
的,Python:怪我咯?

运行IPython 容器

sudo docker run -d --name IPythonApp -p 8888:8888 -e "PASSWORD=your password" -e "USE_HTTP=1" -v /home/zhiyue/repos/ipython-notebook:/notebooks ipython/scipyserver

解析一下参数-d 是未来台的办法运行,--name 是容器的别名,-p
是端口映射,-e
是安装环境变量,那里的环境变量PASSWORD设置成你协调的密码就可以了,USE_HTTP=1
意思是运用http,-v
是安装数据卷,把宿主机的目录挂载到容器里,即便容器被剔除,数据也能够保存下去

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

为了然决这多少个题目,我们只可以不断的多开django进程,同时需要确保所有服务都能急迅的拍卖响应,但思维那其实是一件很不靠谱的作业。

Nginx 反向代理 IPython

有二种艺术,一种是行使官方的Nginx,另一种是采用jwilder /
nginx-proxy
,后一种艺术更加简便易行和便利

联合模型并非不行,因为 overhead
丰硕低,很多工作场景下用同步模型反而会得到更好的功能,比如豆瓣。同步模型最大的题目是对于
IO 密集型业务等待时间丰富长,这时候需要的不是换语言
,而是唤醒你是不是架设要改一下了。

方式1:nginx

  • 应用Nginx的官方镜像nginx

  • Nginx 配置文件
    ipython-server.conf

 map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
 }
server{
        listen 80;
        server_name note.everforget.com;
        location / {
                proxy_pass http://ipython:8888;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}

那一个中要注意一点是,ipython要接纳websock由此要布局websocket,此前在这多少个题目查了遥远。
proxy_pass http://ipython:8888; ipython和后边容器连接时的别名有关。

  • 运行Nginx容器

$ sudo docker run -d -p 80:80 --name nginx --link IPythonApp:ipython  -v `pwd`/config:/etc/nginx/conf.d  -v `pwd`/logs:/var/log/nginx nginx

固然tornado是异步的,不过python的mysql库都不襄助异步,这也就代表假使我们在tornado里面访问数据库,我们依然可能面临因为数据库问题导致的漫天服务不可用。

方式2:nginx-proxy

docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
  • 运行ipython 容器

sudo docker run -d -e "VIRTUAL_HOST=ipython.everforget.com" --name IPython -p 8888:8888 -e "PASSWORD=xxxxxx" -e "USE_HTTP=1" -v /home/zhiyue/repos/ipython-notebook:/notebooks ipython/scipyserver

末段放一张图:

图片 2

如此就能够随时通过web来利用python了。

tornado 是有其一题目,不过 gevent 已经缓解了。我在 node.js
的某问题下已经回答过,对于 node 而言,能采纳的异步模型只有一个,而
Python 就是太多采取了。此外 pypy+tornado+redis
可以随意虐各种长连接的气象,比如自己给我厂写过的一个 push service。

参考


更新日志:

  • 2015-6-8 添加配图
  • 2015-6-6 首次作文

实际异步模型最大的问题在于代码逻辑的隔离,因为是事件触发的,所以我们都是经过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 如故 格林(Green)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导致的代码逻辑割裂,代码逻辑都是逐一的。

这是有代价的,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:怪我咯?