Http server built using Python

David Wheeler had a famous saying:. "Any problem in computer science are combined with another indirect middle layer can be solved by" Python web services in order to improve portability, Python Web server gateway community proposed in PEP 333 in Interface (WSGI, Web Server Gateway Interface).

In order to improve the portability of Python web services, Python community proposed Web Server Gateway Interface (WSGI, Web Server Gateway Interface) in PEP 333 in.
WSGL standard is added to an intermediate layer. , Written in Python HTTP service will be able to interact with it through a middle layer with any Web server. Now, WSGI has become the standard method using Python for HTTP operations.
According to standard definition, the WSGI application can be invoked, and there are two input parameters.

1, WSGI

The following is a first piece of code, the first parameter is Environ, for receiving a dictionary, the dictionary key pair is provided to expand the old set of CGI environment. The second argument itself may be called, the habit will be named start_response (), WSGI application to declare by this parameter response headers.
# Simple HTTP server written in WSGI application form.

#!/usr/bin/env python3 
# A simple HTTP service built directly against the low-level WSGI spec. 
 
from pprint import pformat 
from wsgiref.simple_server import make_server 
 
def app(environ, start_response): 
    headers = {'Content-Type': 'text/plain; charset=utf-8'} 
    start_response('200 OK', list(headers.items())) 
    yield 'Here is the WSGI environment: 
 
'.encode('utf-8') 
    yield pformat(environ).encode('utf-8') 
 
if __name__ == '__main__': 
    httpd = make_server('', 8000, app) 
    host, port = httpd.socket.getsockname() 
    print('Serving on', host, 'port', port) 
    httpd.serve_forever()

These are just a simple case. However, when writing server program, complexity is greatly enhanced. This is because a lot of attention to border points and to fully consider the situation described in the standard.

2, front and reverse Estate Agent

Whether before or reverse proxy to the proxy, HTTP proxy is actually a HTTP server for receiving a request, the request is then received (at least part of the request) for forwarding. Times bother to forward the request to play the role of the client, to forward the HTTP request to the real server, and finally received a response from the server to play a role-playing clients, to forward the request to the real server, the server receives from last the initial response is sent back to the client.
Below is a diagram of the forward proxy and reverse proxy.
Using Python to build http server http server built using Python
Reverse Proxy has been widely used for large HTTP service them. A reverse proxy is a part of Web services for HTTP client is not visible.

3, four architectures

Architects generally use a variety of sophisticated mechanism to build a combination of multiple sub-modules HTTP service. Now in the Python community, it has formed four basic modes. If you have written Python code used to generate dynamic content, and has selected a WSGI support the API or framework, how to deploy HTTP service to line it?

Running a server written using Python, the code server can call WSGI interfaces directly. Now the most popular is the Green Unicorn (Gunicorn) server, but there are other pure Python server ready for production environments.

Configuring mod_wsgi and run Apache, Python code runs in a separate WSFIDaemonProcess, start the daemon by the mod_wsgi.

In the back end is running a similar Gunicorn of Python HTTP server (or any server that supports asynchronous selected frame), then return both a static file to run in the front, but also on the dynamic resource service written in Python reverse proxy Web server.

在最前端运行一个纯粹的反向代理(如Varnish),在该反向代理后端运行Apache或者nginx,在后端运行Python编写的HTTP服务器。这是一个三层的架构。这些反向代理可以分布在不同的地理位置,这样子就能够将离客户端最近的反向代理上的缓存资源返回给发送请求的客户端。

Using Python to build http server http server built using Python
长期以来,对这4个架构的选择主要基于CPython的3个运行时的特性,即解释器占用内存大、解释器运行慢、全局解释器(GIL,Global Interpreter Lock)禁止多个线程同时运行Python字节码。但同时带来了内存中只能载入一定数量的Python实例。

4、平台即服务

这个概念的出现是因为现在的自动化部署、持续集成以及高性能大规模服务的相关技术的出现和处理有一些繁杂。所以有一些提供商提出了PaaS(Platform as a Service),现在只需关心应该如何打包自己的应用程序,以便将自己的应用部署到这些服务之上。
PaaS提供商会解决构建和运行HTTP服务中的出现的各种烦心事。不需要再关心服务器,或者是提供IP地址之类的事情。
PaaS会根据客户规模提供负载均衡器。只需要给PaaS提供商提供配置文件即可完成各种复杂的步骤。
现阶段比较常用的有Heroku和Docker。
大多数PaaS提供商不支持静态内容,除非我们在Python应用程序中实现了对静态内容的更多支持或者向容器中加入了Apache或ngnix。尽管我们可以将静态资源和动态页面的路径放在两个完全不同的URL空间内,但是许多架构师还是倾向于将两者放在同一个名字空间内。

5、不使用Web框架编写WSGI可调用对象

下面第一段代码是用于返回当前时间的原始WSGI可调用对象。

#!/usr/bin/env python3 
# A simple HTTP service built directly against the low-level WSGI spec. 
 
import time 
 
def app(environ, start_response): 
    host = environ.get('HTTP_HOST', '127.0.0.1') 
    path = environ.get('PATH_INFO', '/') 
    if ':' in host: 
        host, port = host.split(':', 1) 
    if '?' in path: 
        path, query = path.split('?', 1) 
    headers = [('Content-Type', 'text/plain; charset=utf-8')] 
    if environ['REQUEST_METHOD'] != 'GET': 
        start_response('01 Not Implemented', headers) 
        yield b'01 Not Implemented' 
    elif host != '127.0.0.1' or path != '/': 
        start_response('404 Not Found', headers) 
        yield b'404 Not Found' 
    else: 
        start_response('200 OK', headers) 
        yield time.ctime().encode('ascii')

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

#!/usr/bin/env python3 
# A WSGI callable built using webob. 
 
import time, webob 
 
def app(environ, start_response): 
    request = webob.Request(environ) 
    if environ['REQUEST_METHOD'] != 'GET': 
        response = webob.Response('501 Not Implemented', status=501) 
    elif request.domain != '127.0.0.1' or request.path != '/': 
        response = webob.Response('404 Not Found', status=404) 
    else: 
        response = webob.Response(time.ctime()) 
    return response(environ, start_response)

第二个是使用Werkzeug编写的WSGI可调用对象返回当前时间。

#!/usr/bin/env python3 
# A WSGI callable built using Werkzeug. 
 
import time 
from werkzeug.wrappers import Request, Response 
 
@Request.application 
def app(request): 
    host = request.host 
    if ':' in host: 
        host, port = host.split(':', 1) 
    if request.method != 'GET': 
        return Response('501 Not Implemented', status=501) 
    elif host != '127.0.0.1' or request.path != '/': 
        return Response('404 Not Found', status=404) 
    else: 
        return Response(time.ctime())

We can compare the difference between these two libraries during a simplified operation, Werkzeug the basis Flask framework.


Guess you like

Origin blog.51cto.com/14414295/2445773
Recommended