diff --git a/localstack/aws/serving/asgi.py b/localstack/aws/serving/asgi.py index 7d4d93683aaa0..5ba09194fdb15 100644 --- a/localstack/aws/serving/asgi.py +++ b/localstack/aws/serving/asgi.py @@ -39,14 +39,14 @@ def __init__( self, gateway: Gateway, event_loop: Optional[AbstractEventLoop] = None, - threads: int = 1000, + threads: int = None, lifespan_listener: Optional[ASGILifespanListener] = None, websocket_listener=None, ) -> None: self.gateway = gateway self.event_loop = event_loop or asyncio.get_event_loop() - self.executor = _ThreadPool(threads, thread_name_prefix="asgi_gw") + self.executor = _ThreadPool(threads or 1000, thread_name_prefix="asgi_gw") self.adapter = ASGIAdapter( WsgiGateway(gateway), event_loop=event_loop, diff --git a/localstack/aws/serving/edge.py b/localstack/aws/serving/edge.py index e4a835a82eb44..08ff45097fd86 100644 --- a/localstack/aws/serving/edge.py +++ b/localstack/aws/serving/edge.py @@ -1,6 +1,7 @@ import logging from typing import List +from localstack import config from localstack.config import HostAndPort from localstack.http.hypercorn import GatewayServer from localstack.runtime.shutdown import ON_AFTER_SERVICE_SHUTDOWN_HANDLERS @@ -21,7 +22,7 @@ def serve_gateway( gateway = LocalstackAwsGateway(SERVICE_PLUGINS) # start serving gateway - server = GatewayServer(gateway, listen, use_ssl) + server = GatewayServer(gateway, listen, use_ssl, config.GATEWAY_WORKER_COUNT) server.start() # with the current way the infrastructure is started, this is the easiest way to shut down the server correctly diff --git a/localstack/config.py b/localstack/config.py index 3cc1baf6aa11f..21898370f6848 100644 --- a/localstack/config.py +++ b/localstack/config.py @@ -655,6 +655,8 @@ def populate_edge_configuration( GATEWAY_LISTEN, ) = populate_edge_configuration(os.environ) +GATEWAY_WORKER_COUNT = int(os.environ.get("GATEWAY_WORKER_COUNT") or 1000) + # IP of the docker bridge used to enable access between containers DOCKER_BRIDGE_IP = os.environ.get("DOCKER_BRIDGE_IP", "").strip() @@ -1114,6 +1116,7 @@ def use_custom_dns(): "EXTRA_CORS_ALLOWED_ORIGINS", "EXTRA_CORS_EXPOSE_HEADERS", "GATEWAY_LISTEN", + "GATEWAY_WORKER_THREAD_COUNT", "HOSTNAME", "HOSTNAME_FROM_LAMBDA", "KINESIS_ERROR_PROBABILITY", diff --git a/localstack/http/hypercorn.py b/localstack/http/hypercorn.py index e68f6bda61682..e14f2e167c797 100644 --- a/localstack/http/hypercorn.py +++ b/localstack/http/hypercorn.py @@ -82,15 +82,19 @@ class GatewayServer(HypercornServer): """ def __init__( - self, gateway: Gateway, listen: HostAndPort | list[HostAndPort], use_ssl: bool = False + self, + gateway: Gateway, + listen: HostAndPort | list[HostAndPort], + use_ssl: bool = False, + threads: int | None = None, ): """ Creates a new GatewayServer instance. :param gateway: which will be served by this server - :param port: defining the port of this server instance - :param bind_address: to bind this server instance to. Can be a host string or a list of host strings. + :param listen: defining the address and port pairs this server binds to. Can be a list of host and port pairs. :param use_ssl: True if the LocalStack cert should be loaded and HTTP/HTTPS multiplexing should be enabled. + :param threads: Number of worker threads the gateway will use. """ # build server config config = Config() @@ -109,7 +113,7 @@ def __init__( # build gateway loop = asyncio.new_event_loop() - app = AsgiGateway(gateway, event_loop=loop) + app = AsgiGateway(gateway, event_loop=loop, threads=threads) # start serving gateway super().__init__(app, config, loop)