Spike on how to leverage tech stack of GraphQL, AWS Lambda and .NetCore
It compares 2 major decisions:
- GraphQL Schema First vs. Graph Type First of GraphQL.Net
- Asp.Net web hosting vs. .Net with handler
It takes 3 experiments:
- GraphQL Graph Type First & Asp.Net web hosting in Graphql.Api.Aspnet.GraphType project
- GraphQL Schema First & Asp.Net web hosting in Graphql.Api.Aspnet.SchemaFirst project
- GraphQL Schema First & .Net with handler in Graphql.Api.Dotnet.SchemaFirst project
The rest part of projects are shared across these projects. Tests also because content is identical.
Database has 2 implementations:
- InMemory - widely used across tests and experiments
- Postgres with EntityFramework - tested and works for local runs
- install DotNet Core 2.1 SDK
- clone this repo
- run in console from repo root dir
- for Mac or Linux
export ASPNETCORE_ENVIRONMENT=Test && dotnet run -p Graphql.Api.Aspnet.GraphType
orexport ASPNETCORE_ENVIRONMENT=Test && dotnet run -p Graphql.Api.Aspnet.GraphType
- for Window PowerShell
$env:ASPNETCORE_ENVIRONMENT=Test; dotnet run -p Graphql.Api.Aspnet.GraphType
or$env:ASPNETCORE_ENVIRONMENT=Test; dotnet run -p Graphql.Api.Aspnet.GraphType
- for Mac or Linux
- open playground in browser http://localhost:5051/playground
- call GraphQL queries
- prepare PostgresDB on your local machine and apply migrations
- follow the previous section with InMemory, but run without environment variable
- for Mac, Linux, Windows PowerShell
dotnet run -p Graphql.Api.Aspnet.GraphType
ordotnet run -p Graphql.Api.Aspnet.GraphType
- for Mac, Linux, Windows PowerShell
- currently not supported
- there is a chance to make it work with LocalStack in Docker, but it won't work out of the box
-
prepare infrastructure (manually at this time, detailed explanation out of scope this time)
- create API GW with
- GET /playground
- POST /graphql
- create new stage or use default /dev one
- create lambda function
- with typical role that API GW can invoke it
- set function name on key
function-name
inaws-lambda-tools-defaults.json
file in your project version - place other details on AWS into this file
- currently used InMemory DB - no need for infra
- create API GW with
-
deploy version
- install dotnet Lambda pugin
- run in console
dotnet lambda deploy-function
in folder of your project version - all details will be taken from
aws-lambda-tools-defaults.json
-
usage
- open playground in browser
- in graphql endpoint add stage name, to match
- run queries
-
limitations
- .Net version do not provider embedded playground - any other playground can be used instead
- install Docker
docker volume create postgres
docker run -d -v /etc/localtime:/etc/localtime:ro -v postgres:/var/lib/postgresql/data:z -p 5432:5432 --name=postgres postgres:9.6
- connect to Postgre service and create role 'Star' with pass 'Wars' and DB 'StarWars'
- run migration commands:
cd graphql.data
dotnet ef migrations add Inital -o ./EntityFramework/Migrations -v # create migration tagged - Inital
dotnet ef update # apply migrations
- implemented DI which allow to cover app with test on different levels (Unit, Integration) and layers (for API, Domain, DB)
- no controllers in my code - all is referenced to mainstream community packages, and tested accordingly
- DI and .Net Core allows to use InMemory DB a lot which decouple Api and Data layers for testability
All performance of Lambda function is controlling throw Memory Limit - CPU, Networking, etc
Lambda memory | AspNet version | .Net version |
---|---|---|
256MB | 5-7sec for first POST request (request of schema) next schema request took ~ 200ms simple query ~ 10ms memory consumtion 56MB 1sec first GET request of playground |
4-4.5sec for first POST request (request of schema) next schema request took ~ 50ms simple query ~ 2-20ms memory consumption 48MB |
1792MB | 850ms for first POST request (request of schema) next schema request took ~ 35ms simple query ~ 4ms memory consumption 98MB 160ms first GET request of playground |
800ms for first POST request (request of schema) next schema request took ~ 6ms simple query ~ 1-5ms memory consumption 87MB. |
In average .Net version consume ~10-15% less memory & faster then Asp.Net version. For more accurate results needed real load testing
Take GraphQL Schema First - it requires less code to write and easier to understand when work on schema.
While it is not full featured as Graph Types - it's better to live with that now, and contribute into future
Take Asp.Net version - while it's not as fast as pure .Net version, it is much easier to work with it on local,
while you develop a lot. It's not hard to replace it in future - just re-write Startup and Handler and you good to go.
For logging used Lambda logger package. It's settings work correctly on local run, but on Lambda - it is not follow settings.
Easy way to read logs not embedded into otnet CLI tool now. Read from CloudWatch. Making it better heavily rely deployment + infra framework
For now there 2 options to choose:
- Serverless
- Terraform + dotnet CLI with plugin
Also SAM - but it didn't fly for me.
Develop plugin to make Schema First better
Initially inspired by: https://github.com/JacekKosciesza/StarWars
Additions: https://github.com/mmacneil/ASPNetCoreGraphQL/tree/master/src/backend/NHLStats.Api