Python服务器编程

8,399 阅读3分钟
原文链接: zhuanlan.zhihu.com

IEEE公布的2017年编程语言排行榜,python高居首位。在百度指数上,python的搜索量也跻身到与java相等的量级,成为最火的语言之一。

那么Python适合用来做服务器编程吗?

首先,看看哪些公司在用Python作为服务器的主要技术栈?可以看到,其中不缺乏一些用户量庞大的公司。

得益于语言的简洁性,python很适合用来进行快速开发,编写出可读性强的程序。那么怎么用python来做服务器编程呢?

从一个例子说起...

这是一个简单的回显服务器,服务端每次从请求读取一些字节并返回给客户端。

但由于服务器是单进程的,如果一个请求占住了服务器,就没办法处理另一个请求。

这次做一些改动,每来一个请求就fork一个进程来处理,这样就不会出现之前的问题。

但多进程模型处理不好会出现僵尸进程和孤儿进程,因此父进程需要处理SIGCHILD信号来收集退出的子进程的信息。

socketserver模块中ForkingMixIn收集子进程的例子:

原始的CGI程序就是使用这种方式,对于每个请求都fork进程来解释cgi程序。

不过随着请求数量的变多,fork进程所带来的开销往往很大。

所以CGI不仅慢...

而且

甚至

后来出现了FastCGI,它与CGI的区别,就是更Fast(误),它是一个常驻进程,预先启动多个cgi进程来等待处理请求。

不同于FastCGI,Apache搞了一套mod_python,使得python解释器可以嵌入在apache进程。

后来PEP 333中定义了WSGI,成为沿用至今的Python web开发的标准协议。

应用WSGI协议的一个示例:

绝大部分的python web开发框架都遵守了这套标准:

gunicorn是一个著名的wsgi http服务器,它采用pre-fork模型来处理和转发请求。

gunicorn包含许多种worker模型:

抛开多进程,现在来看多线程的模型,该方案用线程代替进程来处理每一个请求:

但是为什么许多人说python的多线程是个鸡肋呢?看下面同样的代码,用同步的方式和多线程的方式执行,多线程的代码却执行的更慢...

这到底是什么回事?

这就要说到python中的GIL了,由于GIL的制约,多线程很难充分利用cpu的性能(原图引用

话虽如此,多线程在IO密集型应用上还是有不少用武之地的。下面是多线程在服务器编程的其中一些应用(原图引用

Actor模型

生产者-消费者

concurrent.future在PEP 3148中被定义,它提供了更简单的多进程/多线程API

在很长的一段时间,多进程/多线程的模型都应用的很好,但是

这时候更适合服务器编程的IO多路复用模型开始被广泛应用:

基于事件驱动的异步模型对服务器的资源的有效利用率显然易见

衍生了大量的异步网络框架

在Python 3.4后出现了专门处理异步IO的标准库asyncio

而在随后的Python 3.5后出现了协程语法糖async/await

虽然asyncio成为标准库,但它使用方法却较为复杂,不便于使用,也有人提议要asyncio提供更简洁的接口,也有不少的替代库出现

总的来说,服务器编程经历了从开始的简单到后来的复杂化最终慢慢演变到简单的方式上。