\
Illustrations by Alex Feliksovich
♚ \
Linuxer small eraser, read gu Long and Jin Yong’s novels.
GitHub:github.com/hewenning
Personal blog: www.hewenning.com
David Wheeler famously said, “Any problem in computer science can be solved by adding another layer of indirection.”
To improve the portability of Python Web services, the Python community introduced the Web Server Gateway Interface (WSGI) in PEP 333.
The WSGL standard adds an intermediate layer. Through this middle tier, HTTP services written in Python can interact with any Web server. WSGI is now the standard way to use Python for HTTP operations.
WSGI applications are, by standard definition, callable and have two input parameters.
1, WSGI
Here’s the first piece of code. The first parameter is environ, which receives a dictionary in which the key-value pairs are an extension of the old-style SET of CGI environments. The second parameter itself can be called, conventionally named start_response(), by which WSGI applications declare response header information.
Copy the code
The above is just a simple case. But when writing server programs, the complexity increases dramatically. This is because many of the attention points and boundary cases described in the standard need to be fully considered.
2. Forward proxy and reverse proxy
An HTTP proxy, whether forward or reverse, is simply an HTTP server that receives requests and forwards at least part of the received requests. The forwarding request handler plays the role of a client and sends the forwarded HTTP request to the real server. Finally, the response received from the server plays the role of a client, sends the forwarded request to the real server, and sends the response received from the server back to the original client.
The following is a schematic diagram of forward and reverse proxies.
Reverse proxies have been widely used in large HTTP services. The reverse proxy is part of the Web service and is not visible to HTTP clients. \
3. Four architectures
Architects typically use a variety of complex mechanisms to compose multiple submodules into an HTTP service. In the Python community, there are now four basic patterns. If you’ve written Python code to generate dynamic content, and you’ve chosen an API or framework that supports WSGI, how do you deploy HTTP services online?
- Run a server written in Python that calls WSGI interfaces directly from its code. The most popular is the Green Unicorn (Gunicorn) server, but there are other pure Python servers already available for production.
- configuration
mod_wsgi
Run Apache, run Python code in a separate WSFIDaemonProcess, and start the daemon by mod_WSgi. - Run a Python HTTP server similar to Gunicorn on the back end (or any server that supports the asynchronous framework of your choice), and then run a Web server on the front that can both return static files and reverse proxy dynamic resource services written in Python.
- Run a pure reverse proxy (such as Varnish) on the front end, run Apache or Nginx on the back end, and run an HTTP server written in Python on the back end. This is a three-tier architecture. These reverse proxies can be distributed geographically so that cached resources on the reverse proxy closest to the client can be returned to the client that sent the request.
For a long time, the choice of these four architectures was based primarily on CPython’s three runtime features: the Interpreter takes up a large amount of memory, the Interpreter runs slowly, and the Global Interpreter Lock (GIL) prevents multiple threads from running Python bytecode at the same time. But it also brings up a limit on how many Python instances can be loaded into memory.
Platform as a service
This concept arises because of the complexity of automated deployment, continuous integration, and technologies associated with high-performance large-scale services. So some providers came up with Platform as a Service (PaaS), and now they just need to worry about how to package their applications so that they can deploy their applications on top of these services.
PaaS providers resolve the various irritations that arise in building and running HTTP services. You don’t have to worry about servers, or providing IP addresses or anything like that.
PaaS provides load balancers based on customer size. All you need to do is provide a configuration file to the PaaS provider to complete the various complex steps.
At present, Heroku and Docker are commonly used.
Most PaaS providers do not support static content unless we implement more support for static content in our Python application or add Apache or NgniX to the container. Although it is possible to place the paths of static resources and dynamic pages in two completely different URL Spaces, many architects prefer to place both in the same namespace.
Write WSGI callable objects without using a Web framework
The first piece of code below is the raw WSGI callable that returns the current time.
#! /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('501 Not Implemented', headers) yield b'501 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')Copy the code
The first paragraph is lengthy. The following uses third-party libraries to simplify the schema approach of the original WGSI.
The first example is a callable object written with WebOb that returns the current time.
#! /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)Copy the code
The second is that WSGI callables written in Werkzeug return the current time.
#! /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())Copy the code
You can compare these two libraries in terms of simplifying operations. Werkzeug is the basis of the Flask framework.
Hot recommended in Python create WeChat robot in Python robot to monitor WeChat group chat in Python for cameras and real-time control face open source project | beautification LeetCode warehouse is recommended in Python Python Chinese community’s several kind of public service, announced notice | Python Chinese Community award for articles \
Click to become a registered member of the community ** “Watching” **