Skip to content

Commit 6f52218

Browse files
authored
Issue 108 - Specify LAMBDA_DISPATCH_RUNTIME (#119)
* Issue 108 - Specify LAMBDA_DISPATCH_RUNTIME * Issue 108 - Document settings * Add Docker image links
1 parent 23c4357 commit 6f52218

File tree

4 files changed

+49
-6
lines changed

4 files changed

+49
-6
lines changed

DockerfileLambdaDemoApp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ COPY --from=extension /lambda-dispatch /opt/extensions/lambda-dispatch
3434
# Copy the node.js app
3535
COPY --from=node-build-env /app/dist/ dist/
3636
# This is only used for testing with docker-compose
37+
# It is not necessary to copy this into an app deployed on Lambda
3738
COPY extension/startup.sh ./
3839

3940
# Set the entrypoint

README.md

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,52 @@ Feedback is welcome and encouraged. Please open an issue for any questions, comm
5858

5959
## Project Implementation
6060

61-
The project was built with DotNet 8 and C# and generates a single binary, similar to Go/Rust, that can be used within a Lambda to connect to the AWS Lambda Runtime API to receive invocations. The structure is similar to the [AWS Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter) in that the adapter starts the contained application via a `bootstrap.sh` shell script then connects to that application on port 3000, and checks a `/health` route (which can perform cold start logic). The adapter then connects to the Router over HTTP2 to pickup requests.
61+
The project was initially built in DotNet 8 with C# for both the Router and the Lambda Extension, but the Lambda Extension was later rewritten in Rust using Hyper and the Tokio async runtime to resolve a high CPU usage issue. However, the high CPU usage issue was not resolved directly by the Rust rewrite; instead both the router and extension needed to be restricted to use only 1 worker thread to avoid the high CPU usage; the problem of too much CPU usage was common to the DotNet Router, DotNet Extension, and the Rust Extension.
6262

63-
DotNet on Linux does suffer from a problem that is causing higher-than-necessary CPU usage due to the way spin locks are being used by the thread pool to poll for new work. [High CPU Problem on DotNet on Linux](https://github.com/dotnet/runtime/issues/72153#issuecomment-1216363757) There is a workaround (setting the `DOTNET_ThreadPool_UnfairSemaphoreSpinLimit` env var to 0-6), but the CPU usage is still 2-3x higher than it should be. If this is not resolved in DotNet and if the project needs to exist for a long time, then the project may need to be rewritten in Go or Rust.
63+
The structure of the extension is similar to the [AWS Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter) in that the extension connects to that application on port 3000, and waits for aa `/health` route (which can perform cold start logic) to return a 200 before connecting back to the Router over HTTP2 to pickup requests.
6464

6565
## Installation / Setup
6666

67-
As of 2024-01-01, [fargate.template.yaml](fargate.template.yaml) contains an example deploy, [DockerfileLambda](DockerfileLambda) shows how to package the runtime with a Node.js lambda, and [DockerfileRouter](DockerfileRouter) packages up the router.
67+
As of 2024-02-04, [fargate.template.yaml](fargate.template.yaml) contains an example deploy, [DockerfileLambdaDemoApp](DockerfileLambdaDemoApp) shows how to package the runtime with a Node.js lambda, and [DockerfileRouter](DockerfileRouter) packages up the router.
68+
69+
### Docker Images
70+
71+
The docker images are published to the AWS ECR Public Gallery:
72+
73+
- [Lambda Dispatch Router](https://gallery.ecr.aws/pwrdrvr/lambda-dispatch-router)
74+
- Latest: `public.ecr.aws/pwrdrvr/lambda-dispatch-router:main`
75+
- Available for both ARM64 and AMD64
76+
- [Lambda Dispatch Extension](https://gallery.ecr.aws/pwrdrvr/lambda-dispatch-extension)
77+
- Latest: `public.ecr.aws/pwrdrvr/lambda-dispatch-extension:main`
78+
- Available for both ARM64 and AMD64
79+
- [Lambda Dispatch Demo App](https://gallery.ecr.aws/pwrdrvr/lambda-dispatch-demo-app)
80+
- Latest: `public.ecr.aws/pwrdrvr/lambda-dispatch-demo-app:main`
81+
- Available for both ARM64 and AMD64
82+
83+
### Configuration - Router
84+
85+
The router is configured with environment variables.
86+
87+
| Name | Description | Default |
88+
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------- |
89+
| `LAMBDA_DISPATCH_MaxWorkerThreads` | The maximum number of worker threads to use for processing requests. For best efficiency, set this to `1` and scale up router instances at ~50-70% CPU usage of 1 core. | default DotNet handling |
90+
| `LAMBDA_DISPATCH_ChannelCount` | The number of channels that the Lambda extension should create back to the router | 20 |
91+
| `LAMBDA_DISPATCH_MaxConcurrentCount` | The maximum number of concurrent requests that the Lambda extension should allow to be processed | 10 |
92+
| `LAMBDA_DISPATCH_AllowInsecureControlChannel` | Opens a non-TLS HTTP2 port | false |
93+
| `LAMBDA_DISPATCH_PreferredControlChannelScheme` | The scheme to use for the control channel<br>- `http` - Use HTTP<br>- `https` - Use HTTPS | `https` |
94+
| `LAMBDA_DISPATCH_IncomingRequestHTTPPort` | The port to listen for incoming requests. This is the port contacted by the ALB. | 5001 |
95+
| `LAMBDA_DISPATCH_IncomingRequestHTTPSPort` | The port to listen for incoming requests. This is the port contacted by the ALB. | 5002 |
96+
| |
97+
| `LAMBDA_DISPATCH_ControlChannelInsecureHTTP2Port` | The non-TLS port to listen for incoming control channel requests. This is the port contacted by the Lambda extension. | 5003 |
98+
| `LAMBDA_DISPATCH_ControlChannelHTTP2Port` | The TLS port to listen for incoming control channel requests. This is the port contacted by the Lambda extension. | 5004 |
99+
100+
### Configuration - Lambda Extension
101+
102+
The extension is configured with environment variables.
103+
104+
| Name | Description | Default |
105+
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
106+
| LAMBDA_DISPATCH_RUNTIME | The runtime to use for the Lambda dispatch<br>- `current_thread` - Configures Tokio to use only the current thread for async tasks<br>- `multi_thread` - Configures Tokio to start the multi thread runtime, with a default of 2 threads unless the thread count is specified by `TOKIO_WORKER_THREADS`<br>- `default_multi_thread` - Configures Tokio to start the multi thread runtime with the default behavior of creating as many threads as there are CPU cores | `current_thread` |
68107

69108
## Development
70109

extension/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ fn main() -> anyhow::Result<()> {
7878
.unwrap();
7979
runtime.block_on(async_main())?;
8080
}
81+
// Default or `current_thread` runtime
8182
_ => {
8283
log::info!("Using current_thread runtime");
8384
let runtime = tokio::runtime::Builder::new_current_thread()

fargate.template.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ Resources:
534534
Role: !GetAtt LambdaLBExecutionRole.Arn
535535
Code:
536536
ImageUri: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/lambda-dispatch-demo-app:latest
537-
MemorySize: 256
537+
MemorySize: 192
538538
Timeout: 60
539539
PackageType: "Image"
540540
Architectures:
@@ -544,7 +544,9 @@ Resources:
544544
SubnetIds: [!Ref PrivateSubnet1, !Ref PrivateSubnet2]
545545
Environment:
546546
Variables:
547-
DOTNET_ThreadPool_UnfairSemaphoreSpinLimit: "6"
547+
# No longer needed as we've moved to the Rust runtime
548+
# DOTNET_ThreadPool_UnfairSemaphoreSpinLimit: "6"
549+
LAMBDA_DISPATCH_RUNTIME: "current_thread"
548550

549551
DirectLambda:
550552
Type: AWS::Lambda::Function
@@ -553,7 +555,7 @@ Resources:
553555
Role: !GetAtt LambdaLBExecutionRole.Arn
554556
Code:
555557
ImageUri: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/lambda-dispatch-directlambda:latest
556-
MemorySize: 256
558+
MemorySize: 128
557559
Timeout: 60
558560
PackageType: "Image"
559561
Architectures:

0 commit comments

Comments
 (0)