{"id":289,"date":"2021-08-08T00:00:00","date_gmt":"2021-08-08T00:00:00","guid":{"rendered":"https:\/\/tac.debuzzify.com\/?p=289"},"modified":"2023-06-23T00:26:18","modified_gmt":"2023-06-23T00:26:18","slug":"how-to-serve-massive-computations-using-python-web-apps","status":"publish","type":"post","link":"https:\/\/www.the-analytics.club\/how-to-serve-massive-computations-using-python-web-apps\/","title":{"rendered":"How to Serve Massive Computations Using Python Web Apps."},"content":{"rendered":"\n\n\n

In a previous article<\/b><\/a>, I wrote about the limitations of using Python web apps for analytics projects. Some of the points kindled readers’ curiosity and inspired me to write another story to complement it.<\/p>\n\n\n\n

The central question of this article is, “If Python has severe drawbacks because of its sync behavior, how do platforms such as Instagram and Spotify use it to serve millions around the world?”<\/p>\n\n\n\n

While I have no official information from these platforms (or similar ones), I have insights into handling such massive requests from my experience.<\/p>\n\n\n\n

Here in this article, I prepared a demo to show the basics. A real-life project might have several other technologies in the stack; I haven’t included them all here. But I’ve hinted at some of my favorites in this story and links to resources whenever possible.<\/p>\n\n\n\n

Let’s begin by discussing the sync-async problem again.<\/p>\n\n\n\n

Python’s synchronous behavior and the cost of serving web requests.<\/b><\/h2>\n\n\n\n

Having a lean technology stack is an excellent choice. And the data science community is gifted with Python on that front. Because Python is a general-purpose language, you can use it to build data pipelines, machine learning, web apps, and a lot more.<\/p>\n\n\n\n

A little caveat when using Python web frameworks is its sync behavior. Meaning, Pyhton handles tasks one at a time in every thread. Until the request finishes, others will have to wait in a queue. If you need to serve more concurrent requests, you’ll have to increase the cores and the number of instances.<\/p>\n\n\n\n

If your web app serves only a limited number of users, this isn’t a thing. Also, if you don’t perform heavy computations on-demand, you’re still okay. But when you grow and compute more, your hello world type of web app could cause serious issues.<\/p>\n\n\n\n

This is also true even if you are choosing a Node app. Node is JavaScript-based, and it’s the language’s nature to run asynchronously. The point is the cost is more (if unhandled) when using a Python framework.<\/p>\n\n\n\n

So, let’s handle it.<\/p>\n\n\n\n

Decoupling computation from the request-response cycle.<\/b><\/h2>\n\n\n\n

Imagine, on Instagram, you come across the image of a magnificent blue whale. Stunned by its beauty, you double-tap and like the picture. You wish you could see more of them. But this was the first time you encountered such a majestic photo on the platform.<\/p>\n\n\n\n

You keep scrolling down; the following few images you see are old data science memes and stuff.<\/p>\n\n\n\n

In a few moments, you revisit Instagram. Splendid! You see more giant blue whales swimming and playing with their cubs. It captivates you.<\/p>\n\n\n\n

It is how most platforms work in suggesting content to their users. Immediate learning is not required. They might even lead to false positives as well.<\/p>\n\n\n\n

A clever way to handle this is to decouple computation from the request-response cycle. Use the prior knowledge about the user to serve the immediate request. Accumulate more data to learn and perform better in the future. It is how we see old data science memes by continuing to scroll down and more blue whales in the next visit.<\/p>\n\n\n\n

In large-scale applications, we collect every action of users in a dedicated database. Datastores such as Cassandra<\/b><\/a> are an excellent choice for this purpose. Based on the nature of the application, periodic tasks update the models with new data, or the system uses triggers to do the same. If they happen before your next visit to the platform, you’re lucky to be served by an up-to-date model.<\/p>\n\n\n\n

That’s enough explanation; it’s time to get our hands dirty.<\/p>\n\n\n\n

Performing heavy computations outside web requests.<\/b><\/h2>\n\n\n\n

For simplicity, I’ll be using Flask. But this technique would work in any other Python framework just as well. We use celery to handle heavy computations outside the request-response cycle. Lastly, we will use a database to collect user actions.<\/p>\n\n\n\n

In this demo, we use the request itself as the trigger and begin computation immediately. But it may vary according to the nature of your application. Often, you might have to use a separate pipeline as well. In such scenarios, you may need technologies such as Apache Airflow<\/b><\/a> or Prefect<\/b><\/a>.<\/p>\n\n\n\n

Installing a message broker\u2014Redis.<\/b><\/h3>\n\n\n\n

A message broker does what its name suggests. You can send a message to the broker, and the broker delivers it to all its subscribers simultaneously. Although this definition seems quite simple, life before message brokers was difficult for engineers.<\/p>\n\n\n\n

Here we’ll install Redis, a well-known message broker software. Instead, you can also use RabbitMQ, Amazon SQS, and many other brokers with Celery.<\/p>\n\n\n\n

The Redis official site<\/b><\/a> has instructions for all the OSs. A platform-agnostic way is to use their official docker image.<\/p>\n\n\n\n