如何将 Streamlit 应用部署到 Google App Engine
需要了解的事情
食谱
文件上传器和下载器
自定义运行时
需要了解的事情
将 Streamlit 应用部署到 App Engine 时需要了解一些事项。
灵活的环境是必需的
您必须选择灵活环境,因为它支持 WebSockets,而标准环境不支持。Streamlit
严重依赖 WebSockets 进行服务器和客户端之间的通信。
这是 2021 年 12 月 12 日https://cloud.google.com/appengine/docs/the-appengine-environments的截图。左边是标准环境,右边是灵活环境。
不需要自定义运行时
您无需使用自定义运行时(自定义 Docker 镜像)。
灵活环境提供了官方 Python 运行时,网址为https://cloud.google.com/appengine/docs/flexible/python/runtime,您可以直接使用。
您还可以使用自定义运行时。例如,当您想使用与官方运行时不同的 Python 版本,或者您已经有可用的 Docker 镜像时,这是一个不错的选择。
注意:
截至 2021 年 12 月 12 日,文档显示内置 Python3 运行时的 Python 版本为3.7.2
,但实际上至少在东京地区是3.6.10
已知的。Streamlit 官方仅支持 Python>=3.7,而技术上可以安装 Python 3.6,因此您可能需要按照以下部分设置 Python>=3.7 的自定义运行时。sys.version
asia-northeast1
如果使用st.file_uploader
或,则实例数应为 1st.download_button
如果您的应用包含st.file_uploader
或st.download_button
,则应将最大实例数设置为 1。有关该配置,请参阅https://cloud.google.com/appengine/docs/flexible/python/reference/app-yaml#services。
App Engine 通常会在可用实例之间平均分配请求,因此当存在多个实例时,文件上传/下载请求有时会到达与会话所在的实例不同的实例。
在这种情况下会出现如下错误。
当文件上传出现错误时:文件上传请求到达一个不存在session的服务器,服务器返回400错误码。
当文件下载发生错误时:文件下载请求到达不存在会话的服务器,并返回404响应。
文件上传器/下载器组件出现此问题,因为它们使用普通的无状态 HTTP POST/GET 请求,而其他组件在会话一致的 WebSocket 连接上工作。
虽然我知道至少这些组件存在这个问题,但我不确定是否还有其他组件存在这个问题。我还没有检查所有组件。
注意:
将实例数量限制为 1 有一个缺点,因为它可能会导致一些停机时间。
正如文档所述,灵活实例每周重启一次,当实例数量不足时,这会导致停机。
虽然这个问题已在后续文章中提及,但唯一建议的解决方案是将最小实例数量设置为多个,尽管这与本文所述的解决方案相冲突。我找不到一个能同时解决这两个问题的解决方案。
- App Engine 柔性环境虚拟机实例重启时是否利用了自动扩展?(Stack Overflow)
- 滚动重启会导致 App Engine 应用离线。有什么方法可以修改配置来避免这种情况吗?(Stack Overflow)
注意:
App Engine 提供了会话亲和性设置,但在这种情况下它没有帮助,因为它仅适用于 HTTP 长轮询,如socket.io
文档所述,尽管这个问题是由于不同的原因造成的。
食谱
我将展示一些在不同情况下将 Streamlit 应用部署到 App Engine 的示例。
可以使用下面的命令来部署它们。
$ gcloud app deploy
所有示例资源均可在https://github.com/whitphx/streamlit-appengine-samples上找到。
基本设置
这是最简单的一个。
- 没有自定义运行时
- 无需配置实例数量(扩展)
- 此应用程序不使用文件上传器或下载器。
https://github.com/whitphx/streamlit-appengine-samples/tree/main/helloworld
文件列表
.
├── app.yaml
├── requirements.txt
└── streamlit-app.py
app.yaml
runtime: python
env: flex
runtime_config:
python_version: 3
entrypoint: streamlit run streamlit-app.py --server.port $PORT
- 选择灵活的环境。
- 使用内置的 Python3 运行时。
entrypoint
通过环境变量配置运行指定端口号的Streamlit进程$PORT
。
requirements.txt
streamlit~=1.2.0
streamlit-app.py
import streamlit as st
st.title("App Engine sample app")
name = st.text_input("Your name?")
st.write(f"Hello, {name or 'world'}!")
文件上传器和下载器
这是一个带有文件上传器和下载器的示例。
文件列表
.
├── app.yaml
├── requirements.txt
└── streamlit-app.py
app.yaml
runtime: python
env: flex
runtime_config:
python_version: 3
entrypoint: streamlit run streamlit-app.py --server.port $PORT
automatic_scaling:
max_num_instances: 1
# Or manual scaling as below:
# manual_scaling:
# instances: 1
除了基本设置外,automatic_scaling.max_num_instances
设置为1
。
如果您想使用手动缩放,请使用manual_scaling.instances
。
有关这些设置,请参阅https://cloud.google.com/appengine/docs/flexible/python/reference/app-yaml#services。
requirements.txt
streamlit~=1.2.0
streamlit-app.py
import streamlit as st
st.title("App Engine sample app")
uploaded_file = st.file_uploader("Upload some file")
if uploaded_file:
st.write(f"{uploaded_file.name} was uploaded.")
st.download_button(f"Download {uploaded_file.name}", data=uploaded_file, file_name=uploaded_file.name)
自定义运行时
此示例使用带有的自定义运行时Dockerfile
。
参考:https://cloud.google.com/appengine/docs/flexible/custom-runtimes/build
.
├── Dockerfile
├── app.yaml
├── requirements.txt
└── streamlit-app.py
app.yaml
runtime: custom
env: flex
- 设置
runtime: custom
为使用自定义运行时。 entrypoint
是不需要的,因为它在 中定义Dockerfile
。
Dockerfile
FROM gcr.io/google-appengine/python
# Ref:
# * https://github.com/GoogleCloudPlatform/python-runtime/blob/8cdc91a88cd67501ee5190c934c786a7e91e13f1/README.md#kubernetes-engine--other-docker-hosts
# * https://github.com/GoogleCloudPlatform/python-runtime/blob/8cdc91a88cd67501ee5190c934c786a7e91e13f1/scripts/testdata/hello_world_golden/Dockerfile
RUN virtualenv /env -p python3.7
ENV VIRTUAL_ENV /env
ENV PATH /env/bin:$PATH
ADD requirements.txt /app/
RUN pip install -r requirements.txt
ADD . /app
ENTRYPOINT [ "streamlit", "run", "streamlit-app.py", "--server.port", "8080" ]
- 使用Google官方为App Engine提供的基础镜像
gcr.io/google-appengine/python
。- App Engine 具有健康检查机制,并且官方基础映像已为其配置。
- 请参阅https://cloud.google.com/appengine/docs/flexible/python/customizing-the-python-runtime
- 在创建虚拟环境时指定 Python 版本。
- 该存储库中的一些
Dockerfile
测试数据可以作为参考 - 主进程必须在自定义运行时监听端口 8080。
requirements.txt
streamlit~=1.2.0
streamlit-app.py
import sys
import streamlit as st
st.write(sys.version)