用Python脚本定制自己的Web服务器 推荐
2013-01-23 23:26
267 查看
标题很宏伟,实现很遥远。首先要说明这其实是一个不可能完成的任务,至少不是一片博文就能完成的任务。避免浪费看到标题而满心期待同道的时间。主要是想以Apache为蓝本,通过Python脚本的方式一步一步实现Apache的核心功能。进而了解Python网络编程以及有关于Web服务性能相关的方方面面。闲言少叙,直接上代码!
import socket
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('',1234))server.listen(5)while True: client,addr=server.accept() data=client.recv(1024) client.send("My WebServer") client.close()使用ab命令对这个服务器进行测试:ab -n500 -c500 http://127.0.0.1:1234/测试结果如下:![](../attachment/201301/161613741.png)
可以看到,这个简单几行代码的服务器的吞吐量是每秒2000次。这个服务器除了可以返回字符串“My WebServer”以外,什么都不能干。所以第一步,至少让这个WebServer可以根据用户的请求读取相应的文件返回给客户端。通过打印data可以得到客户端代理提交到WebServer的信息。
GET / HTTP/1.1User-Agent: curl/7.12.1 (i686-redhat-linux-gnu) libcurl/7.12.1 OpenSSL/0.9.7a zlib/1.2.1.2 libidn/0.5.6Host: 127.0.0.1:1234Pragma: no-cacheAccept: */*
我们在这里只关心GET请求的内容,通过解析用户的GET请求后获取指定目录中的文件内容后再返回给客户端。
import socketimport reDocumentRoot="/root/"server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)server.bind(('',1235))server.listen(5)while True: client,addr=server.accept() data=client.recv(1024) m=re.match('GET /(.*) ',data)#由于ab使用的是http1.0 因此与上例有所区别 try: #为应对在进行ab测试时候可能的异常 index=DocumentRoot+m.group(1) html=open(index,"r") client.send(html.read()) client.close() except: client.close()
通过ab命令进行测试的结果如下:
![](../attachment/201301/171900362.png)
可以看到由于增加了匹配用户请求与读写文件的开销,我们的WebServer减少了四分之一的工作性能。可即便如此,我们的Web服务器也要比提供相同服务的Apache服务的吞吐量略胜一筹。以下是Apache服务的吞吐量。
![](../attachment/201301/172628416.png)
事情并没有如此简单,大家都注意到了我们的网页连1k都不到。在真实的生产环境中,网页的大小一般都是50k以上。修改index.html文件,复制5000行My WebServer。
![](../attachment/201301/173221532.png)
如图所示,修改后的文件大小是51k
![](../attachment/201301/173353566.png)
Apache服务器的测试结果。
![](../attachment/201301/175837738.png)
而我们的web服务器由于错误太多,干脆不能进行ab测试。也许你会说因为我们的web服务器是单进程模式,只有当完整完成一次用户请求后才能为下一次请求提供服务。但问题的关键是没有返回标准的http信息头。修改后的代码如下:
import socketimport reDocumentRoot="/root/"server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)server.bind(('',1235))server.listen(5)while True: client,addr=server.accept() data=client.recv(1024) m=re.match('GET /(.*) ',data) try: index=DocumentRoot+m.group(1) html=open(index,"r") index="""HTTP/1.1 200 OKContent-Type: text/html; charset=UTF-8
"""+html.read() client.send(index) client.close() except: client.close()
![](../attachment/201301/231031911.png)
测试结果还是可以让我们满意的。我们的测试都是在本地服务器上进行的,因此网络带宽是被忽略的。因为我们的服务器是单进程的。因此,如果有一个用户处理的比较慢,结果是不堪设想的。
增加多进程后的代码如下:import socketimport reimport osimport sys
DocumentRoot="/root/"server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)server.bind(('',1234))server.listen(5)while True: try: client,addr=server.accept() except: sys.exit(0) if os.fork(): client.close() else: server.close() data=client.recv(1024) m=re.match('GET /(.*) ',data) try: index=DocumentRoot+m.group(1) html=open(index,"r") index="""HTTP/1.1 200 OKContent-Type: text/html; charset=UTF-8
"""+html.read() client.send(index) client.close() except: client.close()
可以通过ab命令的测试了。但测试结果:
![](../attachment/201301/202912198.png)
一直不相上下的吞吐率降到了106.27。让Python落败的原因可以确认就是Python的os.fork()的处理方式,与系统、网络I/O没有直接的关系。
import socket
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('',1234))server.listen(5)while True: client,addr=server.accept() data=client.recv(1024) client.send("My WebServer") client.close()使用ab命令对这个服务器进行测试:ab -n500 -c500 http://127.0.0.1:1234/测试结果如下:
![](../attachment/201301/161613741.png)
可以看到,这个简单几行代码的服务器的吞吐量是每秒2000次。这个服务器除了可以返回字符串“My WebServer”以外,什么都不能干。所以第一步,至少让这个WebServer可以根据用户的请求读取相应的文件返回给客户端。通过打印data可以得到客户端代理提交到WebServer的信息。
GET / HTTP/1.1User-Agent: curl/7.12.1 (i686-redhat-linux-gnu) libcurl/7.12.1 OpenSSL/0.9.7a zlib/1.2.1.2 libidn/0.5.6Host: 127.0.0.1:1234Pragma: no-cacheAccept: */*
我们在这里只关心GET请求的内容,通过解析用户的GET请求后获取指定目录中的文件内容后再返回给客户端。
import socketimport reDocumentRoot="/root/"server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)server.bind(('',1235))server.listen(5)while True: client,addr=server.accept() data=client.recv(1024) m=re.match('GET /(.*) ',data)#由于ab使用的是http1.0 因此与上例有所区别 try: #为应对在进行ab测试时候可能的异常 index=DocumentRoot+m.group(1) html=open(index,"r") client.send(html.read()) client.close() except: client.close()
通过ab命令进行测试的结果如下:
![](../attachment/201301/171900362.png)
可以看到由于增加了匹配用户请求与读写文件的开销,我们的WebServer减少了四分之一的工作性能。可即便如此,我们的Web服务器也要比提供相同服务的Apache服务的吞吐量略胜一筹。以下是Apache服务的吞吐量。
![](../attachment/201301/172628416.png)
事情并没有如此简单,大家都注意到了我们的网页连1k都不到。在真实的生产环境中,网页的大小一般都是50k以上。修改index.html文件,复制5000行My WebServer。
![](../attachment/201301/173221532.png)
如图所示,修改后的文件大小是51k
![](../attachment/201301/173353566.png)
Apache服务器的测试结果。
![](../attachment/201301/175837738.png)
而我们的web服务器由于错误太多,干脆不能进行ab测试。也许你会说因为我们的web服务器是单进程模式,只有当完整完成一次用户请求后才能为下一次请求提供服务。但问题的关键是没有返回标准的http信息头。修改后的代码如下:
import socketimport reDocumentRoot="/root/"server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)server.bind(('',1235))server.listen(5)while True: client,addr=server.accept() data=client.recv(1024) m=re.match('GET /(.*) ',data) try: index=DocumentRoot+m.group(1) html=open(index,"r") index="""HTTP/1.1 200 OKContent-Type: text/html; charset=UTF-8
"""+html.read() client.send(index) client.close() except: client.close()
![](../attachment/201301/231031911.png)
测试结果还是可以让我们满意的。我们的测试都是在本地服务器上进行的,因此网络带宽是被忽略的。因为我们的服务器是单进程的。因此,如果有一个用户处理的比较慢,结果是不堪设想的。
增加多进程后的代码如下:import socketimport reimport osimport sys
DocumentRoot="/root/"server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)server.bind(('',1234))server.listen(5)while True: try: client,addr=server.accept() except: sys.exit(0) if os.fork(): client.close() else: server.close() data=client.recv(1024) m=re.match('GET /(.*) ',data) try: index=DocumentRoot+m.group(1) html=open(index,"r") index="""HTTP/1.1 200 OKContent-Type: text/html; charset=UTF-8
"""+html.read() client.send(index) client.close() except: client.close()
可以通过ab命令的测试了。但测试结果:
![](../attachment/201301/202912198.png)
一直不相上下的吞吐率降到了106.27。让Python落败的原因可以确认就是Python的os.fork()的处理方式,与系统、网络I/O没有直接的关系。
相关文章推荐
- WEB服务器巡检脚本 推荐
- python脚本采集服务器数据通过API提交到django web服务器,然后展示在页面上
- python 3 对dns负载均衡环境下的web服务器的监控脚本
- Python实现简易版的Web服务器(推荐)
- 【脚本语言系列】关于PythonWeb服务器Bottle,你需要知道的事
- 【脚本语言系列】关于PythonWeb客户端-服务器模块http-urllib,你需要知道的事情
- 【脚本语言系列】关于PythonWeb服务器Flask,你需要知道的事
- 【脚本语言系列】关于PythonWeb服务器apache+mod_wsgi,你需要知道的事
- 定制微型linux实现启用虚拟终端基于帐号密码登录、提供ssh服务,提供Web服务(下)附有命令移植脚本 推荐
- [置顶] 自己动手安装turbogears -- 搭建基本Python web开发服务器环境
- 【脚本语言系列】关于PythonWeb服务器Nginx+uWSGI,你需要知道的事
- Apache Web 服务器配置CGI程序,执行Python、Perl脚本
- websocket+Django+python+paramiko实现web页面执行服务器命令和脚本
- [20180310智慧推荐餐厅系统01]配置阿里云服务器Python3和MySql环境
- Python在web开发中简单服务器的搭建与运行问题
- 工具推荐. 在线unix, 在线python/perl脚本测试环境
- Linux 下 将使用Python-Django开发的web应用布置到服务器上(亲测有效)
- [Web 开发] 定制IE下载对话框的按钮(打开/保存) 推荐
- Web服务器压力(负载)测试工具 推荐
- Cron 的在ubuntu 定时执行自己的程序&& Python获取当前 脚本文件的路径。