Skip to content

Commit 4534dd4

Browse files
author
Hanzhang Zeng (Roger)
committed
Merge branch 'dev'
2 parents c93e44f + 05b0360 commit 4534dd4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1751
-297
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
ARG PYTHON_VERSION=3.8
2+
3+
FROM mcr.microsoft.com/azure-functions/python:3.0.14492-python$PYTHON_VERSION
4+
5+
# Mounting local machines azure-functions-python-worker and azure-functions-python-library onto it
6+
RUN rm -rf /azure-functions-host/workers/python/${PYTHON_VERSION}/LINUX/X64/azure_functions_worker
7+
8+
# Use the following command to run the docker image with customizible worker and library
9+
VOLUME ["/azure-functions-host/workers/python/${PYTHON_VERSION}/LINUX/X64/azure_functions_worker"]
10+
11+
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
12+
AzureFunctionsJobHost__Logging__Console__IsEnabled=true \
13+
FUNCTIONS_WORKER_PROCESS_COUNT=1 \
14+
AZURE_FUNCTIONS_ENVIRONMENT=Development
15+
16+
RUN apt-get --quiet update && \
17+
apt-get install --quiet -y git && \
18+
cd /home && \
19+
git clone https://github.com/vrdmr/AzFunctionsPythonPerformance.git && \
20+
mkdir -p /home/site/wwwroot/ && \
21+
cp -r AzFunctionsPythonPerformance/* /home/site/wwwroot/ && \
22+
pip install -q -r /home/site/wwwroot/requirements.txt
23+
24+
CMD [ "/azure-functions-host/Microsoft.Azure.WebJobs.Script.WebHost" ]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
FROM mcr.microsoft.com/azure-functions/python:3.0.14492-python3.6
2+
3+
# Mounting local machines azure-functions-python-worker and azure-functions-python-library onto it
4+
RUN rm -rf /azure-functions-host/workers/python/3.6/LINUX/X64/azure_functions_worker
5+
6+
# Use the following command to run the docker image with customizible worker and library
7+
VOLUME ["/azure-functions-host/workers/python/3.6/LINUX/X64/azure_functions_worker"]
8+
9+
ENV FUNCTIONS_WORKER_RUNTIME_VERSION=3.6 \
10+
AzureWebJobsScriptRoot=/home/site/wwwroot \
11+
AzureFunctionsJobHost__Logging__Console__IsEnabled=true \
12+
FUNCTIONS_WORKER_PROCESS_COUNT=1 \
13+
AZURE_FUNCTIONS_ENVIRONMENT=Development
14+
15+
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 379CE192D401AB61 && \
16+
echo "deb https://dl.bintray.com/loadimpact/deb stable main" | tee -a /etc/apt/sources.list && \
17+
apt-get update && \
18+
apt-get install -y git k6 && \
19+
cd /home && \
20+
git clone https://github.com/vrdmr/AzFunctionsPythonPerformance.git && \
21+
mkdir -p /home/site/wwwroot/ && \
22+
cp -r AzFunctionsPythonPerformance/* /home/site/wwwroot/ && \
23+
pip install -r /home/site/wwwroot/requirements.txt
24+
25+
CMD [ "/azure-functions-host/Microsoft.Azure.WebJobs.Script.WebHost" ]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
FROM mcr.microsoft.com/azure-functions/python:3.0.14492-python3.7
2+
3+
# Mounting local machines azure-functions-python-worker and azure-functions-python-library onto it
4+
RUN rm -rf /azure-functions-host/workers/python/3.7/LINUX/X64/azure_functions_worker
5+
6+
# Use the following command to run the docker image with customizible worker and library
7+
VOLUME ["/azure-functions-host/workers/python/3.7/LINUX/X64/azure_functions_worker"]
8+
9+
ENV FUNCTIONS_WORKER_RUNTIME_VERSION=3.7 \
10+
AzureWebJobsScriptRoot=/home/site/wwwroot \
11+
AzureFunctionsJobHost__Logging__Console__IsEnabled=true \
12+
FUNCTIONS_WORKER_PROCESS_COUNT=1 \
13+
AZURE_FUNCTIONS_ENVIRONMENT=Development
14+
15+
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 379CE192D401AB61 && \
16+
echo "deb https://dl.bintray.com/loadimpact/deb stable main" | tee -a /etc/apt/sources.list && \
17+
apt-get update && \
18+
apt-get install -y git k6 && \
19+
cd /home && \
20+
git clone https://github.com/vrdmr/AzFunctionsPythonPerformance.git && \
21+
mkdir -p /home/site/wwwroot/ && \
22+
cp -r AzFunctionsPythonPerformance/* /home/site/wwwroot/ && \
23+
pip install -r /home/site/wwwroot/requirements.txt
24+
25+
CMD [ "/azure-functions-host/Microsoft.Azure.WebJobs.Script.WebHost" ]
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
#
2+
# NOTE: THIS DOCKERFILE IS SPECIALLY MADE FOR PYTHON 3.9 WORKLOAD.
3+
#
4+
5+
# Build the runtime from source
6+
ARG HOST_VERSION=3.0.14492
7+
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS runtime-image
8+
ARG HOST_VERSION
9+
10+
ENV PublishWithAspNetCoreTargetManifest=false
11+
12+
RUN BUILD_NUMBER=$(echo ${HOST_VERSION} | cut -d'.' -f 3) && \
13+
git clone --branch v${HOST_VERSION} https://github.com/Azure/azure-functions-host /src/azure-functions-host && \
14+
cd /src/azure-functions-host && \
15+
HOST_COMMIT=$(git rev-list -1 HEAD) && \
16+
dotnet publish -v q /p:BuildNumber=$BUILD_NUMBER /p:CommitHash=$HOST_COMMIT src/WebJobs.Script.WebHost/WebJobs.Script.WebHost.csproj -c Release --output /azure-functions-host --runtime linux-x64 && \
17+
mv /azure-functions-host/workers /workers && mkdir /azure-functions-host/workers && \
18+
rm -rf /root/.local /root/.nuget /src
19+
20+
RUN EXTENSION_BUNDLE_VERSION=1.3.3 && \
21+
EXTENSION_BUNDLE_FILENAME=Microsoft.Azure.Functions.ExtensionBundle.1.3.3_linux-x64.zip && \
22+
apt-get update && \
23+
apt-get install -y gnupg wget unzip && \
24+
wget https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION/$EXTENSION_BUNDLE_FILENAME && \
25+
mkdir -p /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION && \
26+
unzip /$EXTENSION_BUNDLE_FILENAME -d /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION && \
27+
rm -f /$EXTENSION_BUNDLE_FILENAME && \
28+
EXTENSION_BUNDLE_VERSION_V2=2.0.1 && \
29+
EXTENSION_BUNDLE_FILENAME_V2=Microsoft.Azure.Functions.ExtensionBundle.2.0.1_linux-x64.zip && \
30+
wget https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V2/$EXTENSION_BUNDLE_FILENAME_V2 && \
31+
mkdir -p /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V2 && \
32+
unzip /$EXTENSION_BUNDLE_FILENAME_V2 -d /FuncExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/$EXTENSION_BUNDLE_VERSION_V2 && \
33+
rm -f /$EXTENSION_BUNDLE_FILENAME_V2 &&\
34+
find /FuncExtensionBundles/ -type f -exec chmod 644 {} \;
35+
36+
FROM buildpack-deps:buster
37+
38+
# ensure local python is preferred over distribution python
39+
ENV PATH /usr/local/bin:$PATH
40+
41+
# http://bugs.python.org/issue19846
42+
# > At the moment, setting "LANG=C" on a Linux system *fundamentally breaks Python 3*, and that's not OK.
43+
ENV LANG C.UTF-8
44+
45+
# extra dependencies (over what buildpack-deps already includes)
46+
RUN apt-get update && apt-get install -y --no-install-recommends \
47+
libbluetooth-dev \
48+
tk-dev \
49+
uuid-dev \
50+
&& rm -rf /var/lib/apt/lists/*
51+
52+
ENV GPG_KEY E3FF2839C048B25C084DEBE9B26995E310250568
53+
ENV PYTHON_VERSION 3.9.0
54+
55+
RUN set -ex \
56+
\
57+
&& wget -O python.tar.xz "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz" \
58+
&& wget -O python.tar.xz.asc "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc" \
59+
&& export GNUPGHOME="$(mktemp -d)" \
60+
&& gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys "$GPG_KEY" \
61+
&& gpg --batch --verify python.tar.xz.asc python.tar.xz \
62+
&& { command -v gpgconf > /dev/null && gpgconf --kill all || :; } \
63+
&& rm -rf "$GNUPGHOME" python.tar.xz.asc \
64+
&& mkdir -p /usr/src/python \
65+
&& tar -xJC /usr/src/python --strip-components=1 -f python.tar.xz \
66+
&& rm python.tar.xz \
67+
&& cd /usr/src/python \
68+
&& gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" \
69+
&& ./configure \
70+
--build="$gnuArch" \
71+
--enable-loadable-sqlite-extensions \
72+
--enable-optimizations \
73+
--enable-option-checking=fatal \
74+
--enable-shared \
75+
--with-system-expat \
76+
--with-system-ffi \
77+
--without-ensurepip \
78+
&& make -j "$(nproc)" \
79+
&& make install \
80+
&& rm -rf /usr/src/python \
81+
&& find /usr/local -depth \
82+
\( \
83+
\( -type d -a \( -name test -o -name tests -o -name idle_test \) \) \
84+
-o \( -type f -a \( -name '*.pyc' -o -name '*.pyo' -o -name '*.a' \) \) \
85+
\) -exec rm -rf '{}' + \
86+
\
87+
&& ldconfig \
88+
&& python3 --version
89+
90+
# make some useful symlinks that are expected to exist
91+
RUN cd /usr/local/bin \
92+
&& ln -s idle3 idle \
93+
&& ln -s pydoc3 pydoc \
94+
&& ln -s python3 python \
95+
&& ln -s python3-config python-config
96+
97+
# if this is called "PIP_VERSION", pip explodes with "ValueError: invalid truth value '<VERSION>'"
98+
ENV PYTHON_PIP_VERSION 20.2.3
99+
# https://github.com/pypa/get-pip
100+
ENV PYTHON_GET_PIP_URL https://github.com/pypa/get-pip/raw/fa7dc83944936bf09a0e4cb5d5ec852c0d256599/get-pip.py
101+
ENV PYTHON_GET_PIP_SHA256 6e0bb0a2c2533361d7f297ed547237caf1b7507f197835974c0dd7eba998c53c
102+
103+
RUN set -ex; \
104+
\
105+
wget -O get-pip.py "$PYTHON_GET_PIP_URL"; \
106+
echo "$PYTHON_GET_PIP_SHA256 *get-pip.py" | sha256sum --check --strict -; \
107+
\
108+
python get-pip.py \
109+
--disable-pip-version-check \
110+
--no-cache-dir \
111+
"pip==$PYTHON_PIP_VERSION" \
112+
; \
113+
pip --version; \
114+
\
115+
find /usr/local -depth \
116+
\( \
117+
\( -type d -a \( -name test -o -name tests -o -name idle_test \) \) \
118+
-o \
119+
\( -type f -a \( -name '*.pyc' -o -name '*.pyo' \) \) \
120+
\) -exec rm -rf '{}' +; \
121+
rm -f get-pip.py
122+
123+
ARG HOST_VERSION
124+
125+
ENV LANG=C.UTF-8 \
126+
ACCEPT_EULA=Y \
127+
AzureWebJobsScriptRoot=/home/site/wwwroot \
128+
HOME=/home \
129+
FUNCTIONS_WORKER_RUNTIME=python \
130+
ASPNETCORE_URLS=http://+:80 \
131+
DOTNET_RUNNING_IN_CONTAINER=true \
132+
DOTNET_USE_POLLING_FILE_WATCHER=true \
133+
HOST_VERSION=${HOST_VERSION}
134+
135+
# Install Python dependencies
136+
RUN apt-get update && \
137+
apt-get install -y wget vim && \
138+
echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections && \
139+
apt-get update && \
140+
apt-get install -y apt-transport-https curl gnupg && \
141+
curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - && \
142+
curl https://packages.microsoft.com/config/debian/9/prod.list > /etc/apt/sources.list.d/mssql-release.list && \
143+
# Needed for libss1.0.0 and in turn MS SQL
144+
echo 'deb http://security.debian.org/debian-security jessie/updates main' >> /etc/apt/sources.list && \
145+
# install necessary locales for MS SQL
146+
apt-get update && apt-get install -y locales && \
147+
echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen && \
148+
locale-gen && \
149+
# install MS SQL related packages
150+
apt-get update && \
151+
apt-get install -y unixodbc msodbcsql17 mssql-tools && \
152+
# .NET Core dependencies
153+
apt-get install -y --no-install-recommends ca-certificates \
154+
libc6 libgcc1 libgssapi-krb5-2 libicu63 libssl1.1 libstdc++6 zlib1g && \
155+
rm -rf /var/lib/apt/lists/* && \
156+
# Custom dependencies:
157+
# OpenCV dependencies:
158+
apt-get update && \
159+
apt-get install -y libglib2.0-0 libsm6 libxext6 libxrender-dev && \
160+
# binutils
161+
apt-get install -y binutils && \
162+
# OpenMP dependencies
163+
apt-get install -y libgomp1 && \
164+
# mysql dependencies
165+
apt-get install -y default-libmysqlclient-dev
166+
167+
COPY --from=runtime-image ["/azure-functions-host", "/azure-functions-host"]
168+
COPY --from=runtime-image [ "/workers/python", "/azure-functions-host/workers/python" ]
169+
COPY --from=runtime-image [ "/FuncExtensionBundles", "/FuncExtensionBundles" ]
170+
171+
RUN pip install grpcio grpcio-tools
172+
173+
RUN cp -r /azure-functions-host/workers/python/3.8 /azure-functions-host/workers/python/3.9 && \
174+
rm -r /azure-functions-host/workers/python/3.9/LINUX/X64/grpc && \
175+
rm -r /azure-functions-host/workers/python/3.9/LINUX/X64/grpcio-1.26.0.dist-info && \
176+
cp -r /usr/local/lib/python3.9/site-packages/grpc /azure-functions-host/workers/python/3.9/LINUX/X64/ && \
177+
cp -r /usr/local/lib/python3.9/site-packages/grpcio-1.32.0.dist-info /azure-functions-host/workers/python/3.9/LINUX/X64/ && \
178+
cp -r /usr/local/lib/python3.9/site-packages/grpc_tools /azure-functions-host/workers/python/3.9/LINUX/X64/ && \
179+
cp -r /usr/local/lib/python3.9/site-packages/grpcio_tools-1.32.0.dist-info /azure-functions-host/workers/python/3.9/LINUX/X64/
180+
181+
RUN cd /azure-functions-host/workers/python/ && \
182+
sed -i 's/3.8"]/3.8", "3.9"]/g' worker.config.json
183+
184+
RUN cd /azure-functions-host/workers/python/3.9 && \
185+
sed -i 's/asyncio.Task.current_task/asyncio.current_task/g' OSX/X64/azure_functions_worker/dispatcher.py && \
186+
sed -i 's/asyncio.Task.current_task/asyncio.current_task/g' LINUX/X64/azure_functions_worker/dispatcher.py
187+
188+
# Mounting local machines azure-functions-python-worker and azure-functions-python-library onto it
189+
RUN rm -rf /azure-functions-host/workers/python/3.9/LINUX/X64/azure_functions_worker
190+
191+
# Use the following command to run the docker image with customizible worker and library
192+
VOLUME ["/azure-functions-host/workers/python/3.8/LINUX/X64/azure_functions_worker"]
193+
194+
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 379CE192D401AB61 && \
195+
echo "deb https://dl.bintray.com/loadimpact/deb stable main" | tee -a /etc/apt/sources.list && \
196+
apt-get update && \
197+
apt-get install -y git k6 && \
198+
cd /home && \
199+
git clone https://github.com/vrdmr/AzFunctionsPythonPerformance.git && \
200+
mkdir -p /home/site/wwwroot/ && \
201+
cp -r AzFunctionsPythonPerformance/* /home/site/wwwroot/ && \
202+
pip install -r /home/site/wwwroot/requirements.txt
203+
204+
ENV FUNCTIONS_WORKER_RUNTIME_VERSION=3.9 \
205+
AzureWebJobsScriptRoot=/home/site/wwwroot \
206+
AzureFunctionsJobHost__Logging__Console__IsEnabled=true \
207+
FUNCTIONS_WORKER_PROCESS_COUNT=1 \
208+
AZURE_FUNCTIONS_ENVIRONMENT=Development
209+
210+
CMD [ "/azure-functions-host/Microsoft.Azure.WebJobs.Script.WebHost" ]
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { check } from "k6";
2+
import { Rate } from "k6/metrics";
3+
import http from "k6/http";
4+
5+
var HOSTNAME = __ENV.HOSTNAME || 'localhost';
6+
var PORT = __ENV.PORT || '80';
7+
var PROTOCOL = __ENV.PROTOCOL || (PORT === '80' ? 'http' : 'https');
8+
9+
// A custom metric to track failure rates
10+
var failureRate = new Rate("check_failure_rate");
11+
12+
// Options
13+
export let options = {
14+
stages: [
15+
// Linearly ramp up from 1 to 50 VUs during first minute
16+
{ target: 25, duration: "1m" },
17+
// Hold at 50 VUs for the next 3 minutes and 30 seconds
18+
{ target: 25, duration: "3m45s" },
19+
// Linearly ramp down from 50 to 0 50 VUs over the last 30 seconds
20+
{ target: 0, duration: "15s" }
21+
// Total execution time will be ~5 minutes
22+
],
23+
thresholds: {
24+
// We want the 95th percentile of all HTTP request durations to be less than 500ms
25+
"http_req_duration": ["p(95)<5000"],
26+
// Thresholds based on the custom metric we defined and use to track application failures
27+
"check_failure_rate": [
28+
// Global failure rate should be less than 1%
29+
"rate<0.01",
30+
// Abort the test early if it climbs over 5%
31+
{ threshold: "rate<=0.05", abortOnFail: true },
32+
],
33+
},
34+
};
35+
36+
// Main function
37+
export default function () {
38+
let response = http.get(`${PROTOCOL}://${HOSTNAME}:${PORT}/api/AsyncHttpTriggerCPUIntensive`);
39+
40+
// check() returns false if any of the specified conditions fail
41+
let checkRes = check(response, {
42+
"status is 200": (r) => r.status === 200
43+
});
44+
45+
// We reverse the check() result since we want to count the failures
46+
failureRate.add(!checkRes);
47+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { check } from "k6";
2+
import { Rate } from "k6/metrics";
3+
import http from "k6/http";
4+
5+
var HOSTNAME = __ENV.HOSTNAME || 'localhost';
6+
var PORT = __ENV.PORT || '80';
7+
var PROTOCOL = __ENV.PROTOCOL || (PORT === '80' ? 'http' : 'https');
8+
9+
// A custom metric to track failure rates
10+
var failureRate = new Rate("check_failure_rate");
11+
12+
// Options
13+
export let options = {
14+
stages: [
15+
// Linearly ramp up from 1 to 50 VUs during first minute
16+
{ target: 25, duration: "1m" },
17+
// Hold at 50 VUs for the next 3 minutes and 30 seconds
18+
{ target: 25, duration: "3m45s" },
19+
// Linearly ramp down from 50 to 0 50 VUs over the last 30 seconds
20+
{ target: 0, duration: "15s" }
21+
// Total execution time will be ~5 minutes
22+
],
23+
thresholds: {
24+
// We want the 95th percentile of all HTTP request durations to be less than 500ms
25+
"http_req_duration": ["p(95)<5000"],
26+
// Thresholds based on the custom metric we defined and use to track application failures
27+
"check_failure_rate": [
28+
// Global failure rate should be less than 1%
29+
"rate<0.01",
30+
// Abort the test early if it climbs over 5%
31+
{ threshold: "rate<=0.05", abortOnFail: true },
32+
],
33+
},
34+
};
35+
36+
// Main function
37+
export default function () {
38+
let response = http.get(`${PROTOCOL}://${HOSTNAME}:${PORT}/api/AsyncHttpTriggerCPUIntensiveWithSleeps`);
39+
40+
// check() returns false if any of the specified conditions fail
41+
let checkRes = check(response, {
42+
"status is 200": (r) => r.status === 200
43+
});
44+
45+
// We reverse the check() result since we want to count the failures
46+
failureRate.add(!checkRes);
47+
}

0 commit comments

Comments
 (0)