Cloud Run has been GA. I wanted to try a python script that used to run locally and take a little time to run in Cloud Run. Containers running in Cloud Run must be able to receive and run requests over HTTP. Cloud Run also has to take into account request timeouts. I will introduce the responder because it was easy to run the script quickly without considering the request timeout.
python's HTTP service framework. Since it implements ASGI (Asynchronous Server Gateway Interface), it can also perform asynchronous processing as the name Asynchronous implies. Asynchronous processing itself can be done with other frameworks. However, when I took a quick look at Flask and Django, which are famous for the python framework, I had to install additional packages and change the configuration file. Looking at the sample code of responder, it seemed easy to install and implement, so I tried using it.
vaivailx@MacBook-Pro-2 responder_sample_for_cloudrun % tree -L 3 .
.
├── Dockerfile
├── requirements.txt
└── src
├── sample.py
└── webapp.py
Each python file does the following:
This is the only requirements.txt.
responder==2.0.4
In Dockerfile, update the package with apt and install the package described in requirements.txt.
FROM python:3.7.5-buster
ENV APP_HOME /app
WORKDIR $APP_HOME
ADD ./requirements.txt /app
ADD ./src /app
# Avoid warnings by switching to noninteractive
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get -y install --no-install-recommends apt-utils dialog 2>&1 \
# Install pylint
&& pip --disable-pip-version-check --no-cache-dir install pylint \
# Update Python environment based on requirements.txt
&& pip --disable-pip-version-check --no-cache-dir install -r requirements.txt \
&& rm -rf requirements.txt \
# Clean up
&& apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
# Switch back to dialog for any ad-hoc use of apt-get
ENV DEBIAN_FRONTEND=
# run app
ENV PORT '8080'
CMD python3 webapp.py
EXPOSE 8080
Processing to accept HTTP request using responder.
Simply prefix def
with ʻasync` and the function will be asynchronous.
webapp.py
import logging
import responder
from sample import process_sample
logging.basicConfig(filename=f'/var/log/webapp.log', level=logging.DEBUG)
api = responder.API()
@api.route("/async")
async def asyncsample(req, resp):
@api.background.task
def process_param(params):
t = int(params.get('time', 10))
process_sample(t)
process_param(req.params)
resp.media = {'async success': True}
@api.route("/sync")
def syncsample(req, resp):
t = int(req.params.get('time', 10))
process_sample(t)
resp.media = {'sync success': True}
if __name__ == '__main__':
api.run()
The log is output because it can be confirmed at runtime with Croud Run. As the route name suggests, accessing the root path / async will execute asynchronous processing, and accessing the root path / sync will execute motivation processing. This time, I tried to sleep for the value of the query parameter.
sample.py
import time
import logging
def process_sample(secs):
logging.debug('process starts.')
time.sleep(secs)
logging.debug('process ends.')
Now, let's set the Cloud Run request timeout to 30 seconds and run it. (Since it is troublesome to wait for 5 minutes, the default value has been changed.)
** Synchronous execution: Execution time 10 seconds **
vaivailx@cloudshell:~ (cloudrun-test-259804)$ date;curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" https://responderasync-jpwo3ltkhq-an.a.run.app/sync?time=10
Fri Dec 13 09:52:59 +09 2019
{"sync success": true}vaivailx@cloudshell:~ (cloudrun-test-259804)$
→ Finished normally
** Synchronous execution: Execution time 40 seconds **
vaivailx@cloudshell:~ (cloudrun-test-259804)$ date;curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" https://responderasync-jpwo3ltkhq-an.a.run.
app/sync?time=40
Fri Dec 13 09:55:45 +09 2019
upstream request timeoutvaivailx@cloudshell:~ (cloudrun-test-259804)$
→ Time out
** Asynchronous execution: Execution time 10 seconds **
vaivailx@cloudshell:~ (cloudrun-test-259804)$ date;curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" https://responderasync-jpwo3ltkhq-an.a.run.app/async?time=10
Fri Dec 13 10:02:31 +09 2019
{"async success": true}vaivailx@cloudshell:~ (cloudrun-test-259804)$
→ Finished normally
** Asynchronous execution: Execution time 40 seconds **
vaivailx@cloudshell:~ (cloudrun-test-259804)$ date;curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" https://responderasync-jpwo3ltkhq-an.a.run.app/async?time=40
Fri Dec 13 10:03:57 +09 2019
{"async success": true}vaivailx@cloudshell:~ (cloudrun-test-259804)$
→ Finished normally
By the way, the HTTP request timeout was up to 900 seconds on the setting screen, but this is not the execution time It is the time from receiving the request to returning the response, and it was confirmed that it can be done for 900 seconds or more if it is asynchronous. The following is the result of asynchronous execution for 1200 seconds.
Recommended Posts