/shiny-load-balancing

Scaling and Load Balancing Shiny for R and Python Apps with Docker

Primary LanguagePythonMIT LicenseMIT

Scaling Shiny Apps for Python and R

We had high hopes for Heroku, as they have a documented option for session affinity. However, for reasons we don’t yet understand, the test application consistently fails to pass. We’ll update this page as we find out more. - Shiny for Python docs

Shiny for R and Python can be deployed in conventional ways, using RStudio Connect, Shiny Server Open Source, and Shinyapps.io.

When it comes to alternative options, the docs tell you to:

  • have support for WebSockets, and
  • use sticky load balancing.

The following options support WebSockets, and deploying with Docker is straightforward Increasing the number of replicas and properly load balancing between them is trickier, but not impossible:

Hosting option Scaling instances Multiple regions
Heroku
DigitalOcean App Platform
Fly.io
Docker Compose

This repository contains supporting material ofr the following blog posts on the Hosting Data Apps (hosting.analythium.io) website:

Testing sticky sessions

We build a Python and an R version of a test application to test how load balancing works. We use this Shiny for Python test application.

Py-Shiny app

The test application is build following the usual Docker workflow for Shiny for Python.

We use the Dockerfile.lb and the app in the load-balancing folder containing the app.py and requirements.txt files.

Build, test run the image, and push to Docker Hub:

# build
# docker build -f Dockerfile.lb -t analythium/python-shiny-lb:0.1 .
docker buildx build --platform=linux/amd64 -f Dockerfile.lb -t analythium/python-shiny-lb:0.1 .

# run: open http://127.0.0.1:8080
docker run -p 8080:8080 analythium/python-shiny-lb:0.1

# push
docker push analythium/python-shiny-lb:0.1

If you are running your container behind a TLS Termination Proxy (load balancer) like Nginx or Caddy, add the option --proxy-headers, this will tell Uvicorn to trust the headers sent by that proxy telling it that the application is running behind HTTPS, etc. - FastAPI docs

Shinylive

Shinylive is an experimental feature (Shiny + WebAssembly) that allows applications to run entirely in a web browser, without the need for a separate server running Python.

We use the load balancing test application and build some static assets based on the Dockerfile-lb-live file:

# build
# docker build -f Dockerfile.lb-live -t analythium/python-shiny-live-lb:0.1 .
docker buildx build --platform=linux/amd64  -f Dockerfile.lb-live -t analythium/python-shiny-live-lb:0.1 .

# run: open http://127.0.0.1:8080
docker run -p 8080:8080 analythium/python-shiny-live-lb:0.1

# push
docker push analythium/python-shiny-live-lb:0.1

The docs folder contains the exported Shinylive site with the static HTML, which is also deployed to GitHub Pages: https://hub.analythium.io/shiny-load-balancing.

R-Shiny app

The R version is a port of the Python app.

# build
# docker build -f Dockerfile.lb-r -t analythium/r-shiny-lb:0.1 .
docker buildx build --platform=linux/amd64 -f Dockerfile.lb-r -t analythium/r-shiny-lb:0.1 .

# run: open http://127.0.0.1:8080
docker run -p 8080:8080 analythium/r-shiny-lb:0.1

# push
docker push analythium/r-shiny-lb:0.1

License

MIT 2022 (c) Analythium Solutions Inc.