Python中的HTTP服务器

发布者:上海IT外包来源:http://www.lanmon.net点击数:1166

David Wheeler有一句名言:“计算机科学中的任何问题都可以通过添加另一层间接中间层来解决。”
为了提高Python Web服务的可移植性,Python社区在PEP 333中提出了Web服务器网关接口(WSGI)。
WSGL标准添加了一个中间层。通过这个中间层,用Python编写的HTTP服务可以与任何Web服务器进行交互。现在,WSGI已成为使用Python进行HTTP操作的标准方法。

根据标准定义,可以调用WSGI应用程序并具有两个输入参数。


1.WSGI
以下是第一段代码,第一个参数是environ,用于接收字典,字典中提供的键值对是旧CGI环境集合的扩展。也可以调用第二个参数本身,通常名为start_response(),WSGI应用程序使用它来声明响应头。

#以WSGI应用程序形式编写的简单HTTP服务。
#!/usr/bin/env python3
#一个直接针对低级WSGI规范构建的简单HTTP服务。
来自pprint import pformat
从wsgiref.simple_server导入make_server
Def app(environ,start_response):
标题={'Content-Type':'text/plain;字符集=UTF-8' }
Start_response('200 OK',list(headers.items()))
Yield'这是WSGI环境:
” .encode( 'UTF-8')收益率pformat(environ).encode('utf-8')
如果__name__=='__ main__':
Httpd=make_server('',8000,app)
主机,端口=httpd.socket.getsockname()
打印('服务于',主机,'端口',端口)
Httpd.serve_forever()

以上只是一个简单的案例。但是在编写服务器程序时,复杂性会大大提高。这是因为充分考虑了标准中描述的许多关注点和边界条件。
2.正向剂和反向剂
无论转发代理还是反向代理,HTTP代理实际上是一个HTTP服务器,它接收请求然后转发收到的请求(至少部分请求)。转发请求时,代理将扮演客户端的角色,将转发的HTTP请求发送给真实服务器,最后从服务器收到的响应将扮演客户端的角色,将转发的请求发送给真实服务器,最后从服务器接收请求。响应将发送回原始客户端。
下面是正向和反向代理的简化图。

反向代理已广泛用于大型HTTP服务。反向代理是Web服务的一部分,HTTP客户端不可见。

3.四种架构
架构师通常使用各种复杂机制将多个子模块组合到一个HTTP服务中。现在在Python社区中,已经形成了四种基本模式。如果您已编写用于生成动态内容的Python代码并选择了支持WSGI的API或框架,那么应该如何将HTTP服务部署到Web?
运行用Python编写的服务器,可以直接从服务器的代码中调用WSGI接口。最受欢迎的是Green Unicorn(Gunicorn)服务器,但还有其他纯Python服务器可以在生产环境中使用。
配置mod_wsgi并运行Apache,在单独的WSFIDaemonProcess中运行Python代码,并通过mod_wsgi启动守护进程。
在后端运行类似于Gunicorn的Python HTTP服务器(或任何支持所选异步框架的服务器),然后在前端运行一个可以返回静态文件的Web和用Python编写的动态资源服务的反向代理。服务器。在前端运行纯反向代理(如Varnish),在反向代理的后端运行Apache或nginx,并在后端运行用Python编写的HTTP服务器。这是一个三层架构。这些反向代理可以分布在不同的地理位置,以便最靠近客户端的反向代理上的缓存资源可以返回给发送请求的客户端。

很长一段时间,这四种体系结构的选择主要基于CPython的三个运行时特性,即解释器占用大量内存,解释器运行缓慢,全局解释器锁(GIL)禁止多线程从同时运行Python。字节码。但与此同时,它只能在内存中加载一定数量的Python实例。

4.平台即服务
由于当今自动化部署,持续集成和高性能,大规模服务的出现和处理的复杂性,出现了这一概念。因此,一些提供商已经提出了PaaS(平台即服务),现在只关心他们应该如何打包他们的应用程序以便将他们的应用程序部署到这些服务。
PaaS提供商将解决构建和运行HTTP服务时出现的各种烦恼。无需关心服务器,或提供IP地址等内容。
PaaS将根据客户规模提供负载均衡器。只需向PaaS提供商提供配置文件即可完成复杂的步骤。
在这个阶段更常用的是Heroku和Docker。
除非我们在Python应用程序中实现对静态内容的更多支持或者将Apache或ngnix添加到容器中,否则大多数PaaS提供程序都不支持静态内容。虽然我们可以将静态资源和动态页面路径放在两个完全不同的URL空间中,但许多架构师更喜欢将它们放在同一个命名空间中。
5.不要使用Web框架来编写WSGI可调用对象
下面的第一段代码是用于返回当前时间的原始WSGI可调用对象。

#!/usr/bin/env python3
#一个直接针对低级WSGI规范构建的简单HTTP服务。
进口时间
Def app(environ,start_response):
Host=environ.get('HTTP_HOST','127.0.0.1')Path=environ.get('PATH_INFO','/')
如果主机:中为“:”
主机,端口=host.split(':',1)
如果'?'在路径:
路径,查询=path.split('?',1)
标题=[('Content-Type','text/plain; charset=utf-8')]
如果environ ['REQUEST_METHOD']!='GET':
Start_response('501 Not Implemented',标题)
收益率b'501未实施'
Elif host!='127.0.0.1'或path!='/':
Start_response('未找到404',标题)
收益率b'404未找到'
否则为:
Start_response('200 OK',标题)
yield time.ctime()。encode('ascii')

第一段相当冗长。以下使用第三方库来简化原始WGSI模式方法。
第一个示例是用WebOb编写的可调用对象,它返回当前时间。

#!/usr/bin/env python3
#使用webob构建的WSGI可调用。
导入时间,webob
Def app(environ,start_response):
Request=webob.Request(environ)
如果environ ['REQUEST_METHOD']!='GET':
Response=webob.Response('501 Not Implemented',status=501)
Elif request.domain!='127.0.0.1'或request.path!='/':Response=webob.Response('404 Not Found',status=404)
否则为:
Response=webob.Response(time.ctime())
返回响应(environ,start_response)

第二种是使用Werkzeug编写的WSGI可调用对象来返回当前时间。
#!/usr/bin/env python3
#使用Werkzeug构建的WSGI可调用。
进口时间
来自werkzeug.wrappers导入请求,响应
@ Request.application
Def app(请求):
Host=request.host
如果主机:中为“:”
主机,端口=host.split(':',1)
如果request.method!='GET':
退货响应('501未实施',状态=501)
Elif host!='127.0.0.1'或request.path!='/':
退货响应('未找到404',状态=404)
否则为:
返回响应(time.ctime())

您可以在简化操作时比较两个库之间的差异。 Werkzeug是Flask框架的基础。





IT外包
>
400-635-8089
立即
咨询
电话咨询
服务热线
400-635-8089
微信咨询
微信咨询
微信咨询
公众号
公众号
公众号
返回顶部