Python Web framework tornado Run and deploy

Source: Internet
Author: User
The example of this article for everyone to share the Python web framework Tornado operation and deployment of detailed content for your reference, the specific content is as follows

First, run and deploy
Because Tornado has its own httpserver built-in, running and deploying it is not the same as other Python web frameworks. Instead of configuring a WSGI container to run your app, you need to write a main () function to start the service:

def main ():  app = Make_app ()  App.listen (8888)  ioloop.current (). Start () if __name__ = = ' __main__ ':  Main ()

Configure your operating system or process manager to run this program to start the service. Note that it may be necessary to increase the maximum number of file handles that each process allows to open (in order to avoid "Too many open files" errors). To increase this limit (for example, set to 50000) you can use the Ulimit command, modify the/etc/security/limits.conf or set Minfds in your Supervisord configuration.

Ii. Processes and Ports
Because of the Python Gil (Global interpreter Lock), it is necessary to run multiple Python processes to make the most of a multi-CPU machine. Typically, it is best to run a process per CPU.

Tornado contains a built-in multi-process mode to start multiple processes at once, which requires a slight change in the main function:

def main ():  app = Make_app ()  server = Tornado.httpserver.HTTPServer (APP)  Server.bind (8888)  Server.start (0) # forks one process per CPU  ioloop.current (). Start ()

This is the simplest way to start a multi-process and let them share the same port, although it has some limitations. First, each subprocess will have its own ioloop, so it is important (and even indirect) to not touch the global Ioloop instance before fork. Second, in this model, it is difficult to do 0 downtime (zero-downtime) updates. Finally, because all processes share the same port, it is more difficult to monitor them separately.

For more complex deployments, it is recommended that you start separate processes and have them listen to different ports individually, and the Supervisord "process groups" feature is a good way. When each process uses a different port, an external load balancer, such as haproxy or nginx, usually needs to provide a single address to the guest.

Third, run behind the load balancer
When running on a load balancer such as Nginx, it is recommended to pass Xheaders=true to Httpserver's constructor. This tells Tornado to use HTTP headers like X-REAL-IP to get the IP address of the user instead of the IP address that all traffic is considered to come from the load balancer.

This is a raw nginx configuration file that is structurally similar to the configuration we used in FriendFeed. This assumes that Nginx and Tornado server are running on the same machine, and that four Tornado servers are running on port 8000-8003:

User nginx;worker_processes 1;error_log/var/log/nginx/error.log;pid/var/run/nginx.pid;events {worker_connections  1024; Use Epoll;}    HTTP {# Enumerate all ' Tornado servers here upstream frontends {server 127.0.0.1:8000;    Server 127.0.0.1:8001;    Server 127.0.0.1:8002;  Server 127.0.0.1:8003;  } include/etc/nginx/mime.types;  Default_type Application/octet-stream;  Access_log/var/log/nginx/access.log;  Keepalive_timeout 65;  Proxy_read_timeout 200;  Sendfile on;  Tcp_nopush on;  Tcp_nodelay on;  gzip on;  Gzip_min_length 1000;  Gzip_proxied any; Gzip_types text/plain text/html text/css text/xml application/x-javascript application/xml application/atom+  XML Text/javascript; # only retry if there is a communication error, not a timeout # on the Tornado server (to avoid propagating "queries of  Death "# to all frontends) Proxy_next_upstream error;    server {Listen 80;    # Allow file uploads client_max_body_size 50M;    Location ^~/static/{  root/var/www;      if ($query _string) {expires Max;    }} location =/favicon.ico {rewrite (. *)/static/favicon.ico;    Location =/robots.txt {rewrite (. *)/static/robots.txt;      } location/{Proxy_pass_header Server;      Proxy_set_header Host $http _host;      Proxy_redirect off;      Proxy_set_header X-real-ip $remote _addr;      Proxy_set_header X-scheme $scheme;    Proxy_pass Http://frontends; }  }}

Iv. static files and file caches
Tornado, you can provide a static file service by specifying a special Static_path in your application:

Settings = {  "Static_path": Os.path.join (Os.path.dirname (__file__), "Static"),  "Cookie_secret": "__todo:_ generate_your_own_random_value_here__ ",  " Login_url ":"/login ",  " xsrf_cookies ": true,}application = Tornado.web.Application ([R "  /", MainHandler),  (R "/login", Loginhandler),  (r "/(Apple-touch-icon\.png ) ", Tornado.web.StaticFileHandler,   dict (path=settings[' Static_path ')),], **settings)

These settings automatically leave all requests beginning with/static/to the static directory, such as Http://localhost:8888/static/foo.png, which will provide the foo.png file through the specified static directory. We will also automatically supply/robots.txt and/favicon.ico from the static directory (although they do not start with the/static/prefix).

In the above settings, we explicitly configure Tornado to get apple-touch-icon.png files from the StaticFileHandler root, although the files are in the static file directory. (The regular expression capturing group must tell StaticFileHandler the file name of the request, and call the capture group to pass the file name as a method parameter to the handler) you can do the same thing, such as providing a sitemap.xml file from the root of the site. Of course, you can also avoid falsifying root apple-touch-icon.png by using tags in your HTML.

In order to improve performance, it is often a good idea for the browser to proactively cache static resources so that the browser does not send unnecessary if-modified-since or Etag requests that might be blocked when the page is rendered, and Tornado uses the static content version Content versioning) to support this feature.

To use these features, use the Static_url method in your template instead of entering the URL of the static file directly in your HTML:

      FriendFeed-{{_ ("Home")}}          

The Static_url () function translates a relative path into a URI similar to/static/images/logo.png?v=aae54. Where the V parameter is a hash (hash) of the logo.png content, And its presence allows the Tornado service to send a cache header to the user's browser, which will allow the browser to cache content indefinitely.

Because the parameter V is based on the file content, if you update a file and restart the service, it will send a new V value, so the user's browser will automatically pull the new file. If the contents of the file are not changed, the browser will continue to use the locally cached copy instead of checking for updates from the server, significantly improving rendering performance.

In production, you may want to provide static files through a more optimal static server, such as Nginx, you can configure any Web server to recognize the version label provided through Static_url () and set the cache header accordingly. Here are some of the nginx-related configurations We used in FriendFeed:

location/static/{  root/var/friendfeed/static;  if ($query _string) {    expires Max;  }}

V, debug mode and auto Reload
If you pass the Debug=true configuration to the application constructor, the application will run in debug/development mode. In this mode, some features to facilitate development will be enabled (each can also be used as a standalone label, and if they are specifically specified, they will be given independent priority):

1. Autoreload=true: The application will observe whether its source file changes and reload itself when any file changes. This reduces the need to manually restart services in development. However, in debug mode, some errors (such as a syntax error in import) can cause the service to shut down and not be automatically recovered.
2. Compiled_template_cache=false: The template will not be cached.
3. Static_hash_cache=false: The static file hash (used by the Static_url function) will not be cached.
4. Serve_traceback=true: When an exception is not captured in RequestHandler, an error page containing the call stack information will be generated.
Auto Reload (autoreload) mode is incompatible with Httpserver's multi-process mode, you cannot pass parameters other than 1 to Httpserver.start (or call tornado.process.fork_processes) When you use Auto reload mode.

The automatic reload function of the debug mode is available as a standalone module located in the Tornado.autoreload. The following two can be used in conjunction to provide additional robustness at the time of syntax errors: setting autoreload=true can detect file modifications while the app is running, and start python-m tornado.autoreload myserver.py To catch arbitrary syntax errors or other startup-time errors.

Overloading will lose any Python interpreter command-line arguments (-u). Because it uses sys.executable and SYS.ARGV to re-execute python. In addition, modifying these variables will cause overloading errors.

On some platforms (including Windows and Mac OSX 10.6), the process cannot be "in-place" updated, so when code updates are detected, the old service exits and starts a new service. This has been known to confuse some Ides.

VI, WSGI and Google App Engine
Tornado are usually run independently and do not require a WSGI container. However, in some environments (such as Google App Engine), only Wsgi is running, and applications cannot run their own services independently. In this case, Tornado supports a limited operating mode that does not support asynchronous operations but allows a subset of tornado ' s functionality in a WSGI environment only. The following features are not supported in WSGI mode, including co-processes, @asynchronous adorners, Asynchttpclient,auth modules, and WebSockets.

You can use Tornado.wsgi.WSGIAdapter to convert a tornado application into a WSGI application. In this example, configure your WSGI container to discover the Application object:

Import Tornado.webimport tornado.wsgiclass MainHandler (tornado.web.RequestHandler):  def get (self):    Self.write ("Hello, World") Tornado_app = Tornado.web.Application ([  (R "/", MainHandler),]) application = Tornado.wsgi.WSGIAdapter (Tornado_app)

The above is the whole content of this article, I hope that everyone's study has helped.

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.