Tornado Web Server on Elastic Beanstalk

Tornado Web Server on Elastic Beanstalk

Using Tornado Web server for Python on Elastic Beanstalk isn’t quite straightforward. There isn’t much information on the internet, either. The objective of this article is to be a guide and reference.

Tornado Web Server uses non-blocking IO to support thousands of connections in parallel. It is different from most Python web frameworks. It is not based on WSGI, and it is typically run with only one thread per process. Tornado is integrated with the standard library asyncio module and shares the same event loop (by default since Tornado 5.0). In general, libraries designed for use with asyncio can be mixed freely with Tornado.

The AWS Elastic Beanstalk Python platform is a set of environment configurations for Python web applications that can run behind an Apache proxy server with WSGI. Each configuration corresponds to a version of Python, such as Python 3.4.

Integrating Tornado and WSGI servers like (UWSGI) could be troublesome. Let’s try to integrate an example “Hello World” Tornado application with UWSGI.

Below is a simple Hello World example of Tornado

import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")

def make_app():
    return tornado.web.Application([
        (r"/", MainHandler),
    ])

application=make_app()

It is better to test your application on a Centos platform (which is the same flavor as Amazon Linux) before pushing to Beanstalk. Installing UWSGI on Centos isn’t quite straightforward. The commands to install UWSGI on Centos 7 is as below

yum update
yum install yum-utils
yum groupinstall development
yum install https://centos7.iuscommunity.org/ius-release.rpm


#Install python3.6 and pip3.6
yum install python36u
yum install -y python36u-pip
yum install python36u-devel


# Install uwsgi
pip3.6 install uwsgi


#Install dependencies
pip3.6 install -t deps -r requirements.txt --upgrade

We will be using UWSGI server to integrate with Tornado, and a simple HTTP socket-based UWSGI configuration is given below.

[uwsgi]
module=app
plugins=python36u
http-socket = 0.0.0.0:8080
master = true
http-to = /tmp/uwsgi.sock

When UWSGI is run we might see the below error:

*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 13806)
spawned uWSGI worker 1 (pid: 13807, cores: 1)
TypeError: __call__() takes 2 positional arguments but 3 were given
[pid: 13807|app: 0|req: 1/1] 127.0.0.1 () {24 vars in 254 bytes} [Thu Mar 21 23:42:39 2019] GET / => generated 0 bytes in 0 msecs (HTTP/1.1 500) 0 headers in 0 bytes (0 switches on core 0)

To fix the above error, app.py is updated to below (note that Tornado > 6.x doesn’t have torando.wsgi.*, the version used in this example is 5.1.1):

import sys
import tornado.ioloop
import tornado.web
import tornado.wsgi

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")

def make_app():
    return tornado.web.Application([
        (r"/", MainHandler),
    ])

application=tornado.wsgi.WSGIAdapter(make_app())

Above file and along with all the required dependencies can be now bundled and deployed to Elastic Beanstalk.

from DZone Cloud Zone

Sharing is caring!

Comments are closed.