Serverless: Flask based Online Python/Ruby/JavaScript Compiler & Runner using AWS Lambda

Welcome Page of our website

Recently I created a serverless online compiler & runner web app to run Pyhon, Ruby and JavaScript code by using the Flask framework and AWS Lambda Function service, as the 3rd assignment of the course ECE1779 (Introduction to Cloud Computing). Here I just want to share some experience and summarize what we have done and hopefully I could get some feedback.

Below is a screenshot about our online code editor and it supports custom test case, multiple programming languages including Python, Ruby, and JavaScript, but most importantly, it is serverless.

Screenshot for problem page where user write and test the code

Function as a Service

From the Wikipedia

Function as a service (FaaS) is a category of cloud computing services that provides a platform allowing customers to develop, run, and manage application functionalities without the complexity of building and maintaining the infrastructure typically associated with developing and launching an app

Compared with Platform as a Service(PaaS), FaaS is easier to scale up/down and more money-saving because we do not need to pay for the entire server in the cloud except the resource consumed during the execution time. Since the third party would find a server to provide the run-time environment and scale up/down whenever necessary, the only thing we need to consider is just a piece of code that we wrote as a function. For this reason, it saves much trouble for developers to set up and administer servers.

AWS Lambda Function

In 2014, AWS introduced the Lambda function service, with which you do not need to buy a server to host your web application. Just as the name goes, what you need to do is to write a function and AWS will choose one server to run it and handle all the back-end environment issues. For this reason, your web app has to be stateless, unlike a normal server, you will not have a perpetual process running on a server and waiting for HTTP requests. For example, the session stored on the server side would not work in a serverless website. This is a very big difference from the traditional web server.

To trigger a Lambda Function, an event mechanism is used to trigger the execution of the function with input payload in JSON format. This event can be an API call(by using AWS API Gateway), S3 bucket events like createing or deleting an object, updates made to the DynamoDB table and other supported AWS services.

Note : In the following parts, I will only explain the detail about how to compile and run python/ruby/JavaScript/java code by using Lambda function and I will assume that you already know how to build and deploy your Flask web app, set up a virtual environment.

How to deploy serverless Flask website?

Zappa is used to easily build and deploy our Flask based web service on AWS Lambda + API Gateway. Below are some commonly used commands.

pip install zappa #Installation
zappa init #Initialization
zappa deploy #Deployment (only used for the first time)
zappa update #Update your change(make updates after first deployment)

How to compile & run code in AWS Lambda?

Currently AWS Lambda only support the runtime environment for the following languages.

  • Python
  • Java
  • Node.js
  • C#

So how to compile and run different kinds of code our user submitted?

How to run Python code?

Since Python is an interpreter based programming language, we can directly read the code from an external link and execute the code inside a python code by using exec() function.

The code below firstly read a code through a S3 url, then execute the code with a specific name and a custom input, return the stdout and any unexpected error if necessary.

The code url, custom input and function name are got from the JSON event, following is an example

How to run Ruby/JavaScript code?

Similarly, Ruby and JavaScript are interpreter based languages, but AWS Lambda function does not support these languages. Our method is to upload the Ruby environment to Lambda and use the child process in the Node.js environment by referring to this article (Scripting Languages for AWS Lambda: Running PHP, Ruby, and Go) from the AWS blog.

Even though Lambda function is stateless, there still exists a temp folder that we could use to write and read file during the execution. Therefore, we could download the code user submitted into that temp folder and import that code in our Ruby/JavaScript code to run specific function with a custom testcase.

To run a ruby code, we have a ruby code (evaluate.rb) to run a Ruby funtion with name and input as parameters, which we get from the Lambda event.

And a JavaScript code to download the Ruby code from S3 and execute that evaluate.rb code by using the child process.

To run a JavaScript code, we just need a JavaScript code to download the code from S3, store it in the /tmp folder, execute it and return the stdout and stderr.

How to run other codes?

In the above parts, we manually upload the environment to compile and run other languages’ code which AWS Lambda currently does not support. Similarly we can use this method to support any other languages. We can just upload the compile and executable environment together with the code to execute a series of command to compile and run the code user submitted.

Unfortunately, there is limitation (around 200MB) for the size of the package we upload to Lambda. For example, Java JDK is too large to upload to Lambda and we only have JRE in the Java runtime environment. Therefore we cannot compile java code directly in Lambda.

A way to solve this problem is to use an EC2 server to compile and run the java code remotely through some methods like sending specific bash commands using the EC2 System Manager. It is doable but, obviously this method obeys the serverless we insist in the beginning and we do not recommend this high-latency, cumbersome method.

Hopefully, one day AWS will provide more permissions for user to custom the Lambda environment or increase the maximum size of the space for user use. Then we could run code of any other languages.

Overall architecture

Below is the overall architecture of our online coding service for your reference. I did not explain every component of our web service in this article and if there are problems or anything you are interested to know, please reply to me. And I may make my GitHub repository for this project public if that would be helpful.

Keyword: Serverless, AWS Lambda, API Gateway, Cognito, DynamoDB, S3, Flask

Overall System Architecture