Repository: GoogleCloudPlatform/functions-framework-python
Pull request #195 (2022-08-08 21:24:44)

feat: Scale gunicorn server to serve 1000 concurrent requests
Change the gunicorn server setting and set the max threads to 1000


Patch:
diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml
index 940bdf5..09752c9 100644
--- a/.github/workflows/conformance.yml
+++ b/.github/workflows/conformance.yml
@@ -24,46 +24,55 @@ jobs:
         go-version: '1.16'
 
     - name: Run HTTP conformance tests
-      uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.1.0
+      uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.6.0
       with:
-        version: 'v1.1.0'
+        version: 'v1.6.0'
         functionType: 'http'
         useBuildpacks: false
         validateMapping: false
         cmd: "'functions-framework --source tests/conformance/main.py --target write_http --signature-type http'"
 
     - name: Run event conformance tests
-      uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.1.0
+      uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.6.0
       with:
-        version: 'v1.1.0'
+        version: 'v1.6.0'
         functionType: 'legacyevent'
         useBuildpacks: false
         validateMapping: true
         cmd: "'functions-framework --source tests/conformance/main.py --target write_legacy_event --signature-type event'"
 
     - name: Run CloudEvents conformance tests
-      uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.1.0
+      uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.6.0
       with:
-        version: 'v1.1.0'
+        version: 'v1.6.0'
         functionType: 'cloudevent'
         useBuildpacks: false
         validateMapping: true
         cmd: "'functions-framework --source tests/conformance/main.py --target write_cloud_event --signature-type cloudevent'"
 
     - name: Run HTTP conformance tests declarative
-      uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.1.0
+      uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.6.0
       with:
-        version: 'v1.1.0'
+        version: 'v1.6.0'
         functionType: 'http'
         useBuildpacks: false
         validateMapping: false
         cmd: "'functions-framework --source tests/conformance/main.py --target write_http_declarative'"
 
     - name: Run CloudEvents conformance tests declarative
-      uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.1.0
+      uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.6.0
       with:
-        version: 'v1.1.0'
+        version: 'v1.6.0'
         functionType: 'cloudevent'
         useBuildpacks: false
         validateMapping: true
         cmd: "'functions-framework --source tests/conformance/main.py --target write_cloud_event_declarative'"
+
+    - name: Run HTTP concurrency tests declarative
+      uses: GoogleCloudPlatform/functions-framework-conformance/action@v1.6.0
+      with:
+        version: 'v1.6.0'
+        functionType: 'http'
+        useBuildpacks: false
+        validateConcurrency: true
+        cmd: "'functions-framework --source tests/conformance/main.py --target write_http_declarative_concurrent'"
\ No newline at end of file
diff --git a/src/functions_framework/_http/gunicorn.py b/src/functions_framework/_http/gunicorn.py
index 25fdb79..f522b67 100644
--- a/src/functions_framework/_http/gunicorn.py
+++ b/src/functions_framework/_http/gunicorn.py
@@ -20,7 +20,7 @@ class GunicornApplication(gunicorn.app.base.BaseApplication):
         self.options = {
             "bind": "%s:%s" % (host, port),
             "workers": 1,
-            "threads": 8,
+            "threads": 1024,
             "timeout": 0,
             "loglevel": "error",
             "limit_request_line": 0,


Test patch:
diff --git a/tests/conformance/main.py b/tests/conformance/main.py
index e790f62..67926ff 100644
--- a/tests/conformance/main.py
+++ b/tests/conformance/main.py
@@ -1,4 +1,5 @@
 import json
+import time
 
 from cloudevents.http import to_json
 
@@ -46,3 +47,9 @@ def write_http_declarative(request):
 @functions_framework.cloud_event
 def write_cloud_event_declarative(cloud_event):
     _write_output(to_json(cloud_event).decode())
+
+
+@functions_framework.http
+def write_http_declarative_concurrent(request):
+    time.sleep(1)
+    return "OK", 200
diff --git a/tests/test_http.py b/tests/test_http.py
index bd301c9..3414aaf 100644
--- a/tests/test_http.py
+++ b/tests/test_http.py
@@ -97,7 +97,7 @@ def test_gunicorn_application(debug):
     assert gunicorn_app.options == {
         "bind": "%s:%s" % (host, port),
         "workers": 1,
-        "threads": 8,
+        "threads": 1024,
         "timeout": 0,
         "loglevel": "error",
         "limit_request_line": 0,
@@ -105,7 +105,7 @@ def test_gunicorn_application(debug):
 
     assert gunicorn_app.cfg.bind == ["1.2.3.4:1234"]
     assert gunicorn_app.cfg.workers == 1
-    assert gunicorn_app.cfg.threads == 8
+    assert gunicorn_app.cfg.threads == 1024
     assert gunicorn_app.cfg.timeout == 0
     assert gunicorn_app.load() == app