Person som mediterar

Andas in, andas ut

Kommer du ihåg sist dina tankar var tysta? Inget brus, inga tankar om vad du ska göra på jobbet imorgon eller hur budgeten ser ut för nästa månad? Alla måsten och orosmoln som panikslaget väcker dig mitt i natten svettig och med hjärtat i halsgropen.

Det kallas stress och klassas idag som en folksjukdom och är ett av samhällets största problem. Över 50% av alla sjukskrivningar beror på en reaktion på långvarig stress. På det där lilla eller stora bruset som jagar oss och bryter ner vårt immunförsvar.

Vi har nog alla varit vid en punkt i livet där vi känner att det är mycket som pågår. Kanske är det just nu? Efter en långvarig pandemi lever vi istället vid sidan om ett krig som känns alldeles för nära. Kanske är det mycket på jobbet, oroliga anställda eller hur ska du förklara vad som pågår i världen för dina barn?

Då har jag ett tips för dig och det är att börja meditera.  Meditationen har verkligen förändrat mitt liv. Det är onekligen ett uttjatat uttryck men jag vet inte hur jag ska beskriva det annars. Jag kan tillägga att jag hade kunnat stå i spetsen av en motståndsrörelse mot just denna aktivitet i hela mitt liv om det hade funnits. Tur att man får ändra åsikter. 

Något jag alltid trodde var att meditation var väldigt svårt att komma igång med. Kanske är det fler som känner igen sig? Jag hade en målat upp en bild av att jag behövde ha på mig en viss typ av kläder, det skulle vara morgon eller kväll och på något sätt trodde jag att jag behövde vara 150% hängiven meditationen för att ens kunna prova. Som på ett sätt är sant men samtidigt helt falskt.

Att meditera är svårt just på grund av den vanemässiga stressen våra kroppar är så acklimatiserade till. Det kan kännas som en omöjlighet att inte låta tankarna sväva iväg. I början kan det vara nästan mer stressande att försöka meditera än att strunta i det och harva vidare i hamsterhjulet. Det känns läskigt att gå så djupt inom oss själva, vilka tankar ska dyka upp, hur kommer jag känna och kommer jag ens att klara det? Det är så mycket mer bekvämt att vara lite stressad och sitta klistrad vid datorn eller telefonen för det är vad våra kroppar är vana vid. Man skulle kunna säga att vi skapat ett beroende av att alltid vara lite stressade, att alltid ligga två steg fram och att faktiskt aldrig befinna oss där vi är; Här och nu.

Men, det är just det som är en stor del av meditationen. Meditation behöver aldrig vara perfekt för att den är på sitt sätt helt kravlös. Varje gång du mediterar och gång på gång återför tankarna till situationen blir du lite mer uppmärksam på nuet. För varje meditation dövas bruset och de där oönskade tankarna blir färre och färre. Det handlar inte om perfektionen utan om att grunda oss själva och befinna oss här och nu några extra sekunder varje dag. Efter bara en vecka blir dom sekunderna till minuter som blir till timmar. Ni förstår min poäng gissar jag.

Här är några enkla tips som hjälpte mig när jag började med meditation:

  1. En meditation behöver inte vara lång. Så lite som 2-5 minuter är faktiskt allt som krävs i början.
  2. Var snäll mot dig själv. Det gör inget om dina tankar smiter iväg, för dem bara vänligt men bestämt tillbaka och lägg ingen vidare energi på det.
  3. Du behöver inte vara klädd på ett visst sätt och det behöver inte vara varken morgon eller kväll för att du ska kunna meditera. Att meditera är kravlöst och kan egentligen göras var och hur som helst. I jeans eller underkläder, på en specialdesignad meditationskudde eller i kontorsstolen
  4. Om det känns svårt att veta hur du ska börja så rekommenderar jag  att ladda ner en meditationsapp. Där finns guidade meditationer från nybörjare till proffs och jag tycker fortfarande att det enklare att bli guidad än att kasta mig ut ensam.
  5. I början är det viktigast att vara kontinuerlig. Meditationerna kommer kanske inte vara så kvalitativa och tankarna kommer flyga åt höger och vänster i en rasande fart och det är helt okej. För varje gång du för tankarna tillbaka till mantrat eller andningen blir du lite, lite bättre på att hålla fokuset här och nu.
  6. Sist men inte minst. Av alla moment i ditt liv är detta en av de som ska vara helt kravlöst. Syftet är att få dig medveten om nuet och inte springa till framtiden eller älta gårdagen. Det är bara du och din andning.

Lycka till och glöm inte att då och då stanna upp och uppskatta här och nu!

Bok och kaffekopp

Johanna Grahn
Marketing Intern

Vill du veta mer om oss på Developers Bay?


Utvecklare som sitter vid laptop

Running a GraphQL API in .NET 6 on AWS Lambda

Introduction

 

I recently set up a brand new API for a client. AWS and .NET were givens, the remaining choices were up to me. This article is my way of writing down all the things I wish I knew when I started that work. I assume you already know your way around .NET 6C# 10GraphQL and have your ~/.aws/credentials configured.

Why GraphQL

 

GraphQL has quickly become my primary choice when it comes to building most kinds of APIs for a number of reasons:

  • Great frameworks available for a variety of programming languages
  • Type safety and validation for both input and output is built-in (including client-side if using codegen)
  • There are different interactive “swaggers” available, only much better

 

Something often mentioned about GraphQL is that the client can request only whatever fields it needs. In practice I find that a less convincing argument because most of us are usually developing our API for a single client anyway.

For the .NET platform my framework of choice is Hot Chocolate. It has great docs and can generate a GraphQL schema in runtime based on existing .NET types.

Why Lambda

 

Serverless is all the hype now. What attracts me most is the ease of deployment and the ability to dynamically scale based on load.

AWS Lambda is usually marketed (and used) as a way to run small isolated functions. Usually with 10 line Node.js examples. But it is so much more! I would argue it is the quickest and most flexible way to run any kind of API.

 

The only real serverless alternative on AWS is ECS on Fargate, but that comes with a ton of configuration and also requires you to run your code in Docker.

 

Initial application setup

 

We start by creating a new dotnet project:

 

dotnet new web -o MyApi && cd MyApi

 

Add AspNetCore and HotChocolate:

 

dotnet add package DotNetCore.AspNetCore --version "16.*"
dotnet add package HotChocolate.AspNetCore --version "12.*"

 

Add a single GraphQL field:

 

// Query.cs
using static System.Runtime.InteropServices.RuntimeInformation;

public class Query {
  public string SysInfo =>
    $"{FrameworkDescription} running on {RuntimeIdentifier}";
}

 

Set up our AspNetCore application (using the new minimal API):

 

// Program.cs
var builder = WebApplication.CreateBuilder(args);

builder.Services
  .AddGraphQLServer()
  .AddQueryType<Query>();

var app = builder.Build();

app.UseRouting();

app.UseEndpoints(endpoints =>
  endpoints.MapGraphQL());

await app.RunAsync();

Running locally

 

Let’s verify that our GraphQL API works locally.

 

Start the API:

dotnet run

 

Verify using curl:

curl "http://localhost:<YourPort>/graphql?query=%7B+sysInfo+%7D"

 

You should see a response similar to:

 

{ "data": { "sysInfo":".NET 6.0.1 running on osx.12-x64" } }

 

Lambda runtimes

 

AWS offers a number of different managed runtimes for Lambda, including .NET Core, Node, Python, Ruby, Java and Go. For .NET the latest supported version is .NET Core 3.1, which I think is too old to base new applications on.

.NET 6 was released a few months ago, so that’s what we’ll be using. There are two main alternatives for running on a newer runtime than what AWS provides out of the box:

 

  • Running your Lambda in Docker
  • Using a custom runtime

 

Running your Lambda in Docker was up until recently the easiest way for custom runtimes. The Dockerfile was only two or three lines and easy to understand. But I still feel it adds a complexity that isn’t always justified.

Therefore we will be using a custom runtime.

 

Using a custom runtime

 

There is a hidden gem available from AWS, and that is the Amazon.Lambda.AspNetCoreServer.Hosting nuget package. It’s hardly mentioned anywhere except in a few GitHub issues, and has a whopping 425 (!) downloads as I write this. But it’s in version 1.0.0 and should be stable.

 

Add it to the project:
dotnet add package Amazon.Lambda.AspNetCoreServer.Hosting --version "1.*"

 

Then add this:

// Program.cs
...
builder.Services
  .AddAWSLambdaHosting(LambdaEventSource.HttpApi);
...

 

The great thing about this (except it being a one-liner!) is that if the application is not running in Lambda, that method will do nothing! So we can continue and run our API locally as before.

 

Bootstrapping

 

There are two main ways of bootstrapping our Lambda function:

  • Changing the assembly name to bootstrap
  • Adding a shell script named bootstrap

 

Changing the assembly name to bootstrap could be done in our .csproj. Although it’s a seemingly harmless change, it tends to confuse developers and others when the “main” dll goes missing from the build output and an extensionless bootstrap file is present instead.

Therefore my preferred way is adding a shell script named bootstrap:

 

// bootstrap
#!/bin/bash

${LAMBDA_TASK_ROOT}/MyApi

 

 

LAMBDA_TASK_ROOT is an environment variable available when the Lambda is run on AWS.

We also need to reference this file in our .csproj to make sure it’s always published along with the rest of our code:

 

 

// MyApi.csproj
...
<ItemGroup>
  <Content Include="bootstrap">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </Content>
</ItemGroup>
...

Creating the Lambda package

 

We will be using the dotnet lambda cli tool to package our application. (I find it has some advantages over a plain dotnet publish followed by zip.)

 

dotnet new tool-manifest
dotnet tool install amazon.lambda.tools --version "5.*"

 

I prefer to install tools like this locally. I believe global tools will eventually cause you to run into version conflicts.

We also add a default parameter to msbuild, so we don’t have to specify it on the command line.

 

// aws-lambda-tools-defaults.json
{
  "msbuild-parameters": "--self-contained true"
}

 

Building and packaging the application is done by
dotnet lambda package -o dist/MyApi.zip

 

Deploying to AWS

 

The way I prefer to deploy simple Lambdas is by using the Serverless framework.

(For an excellent comparison between different tools of this kind for serverless deployments on AWS, check out this post by Sebastian Bille.)

You might argue that Terraform has emerged as the de facto standard for IaC. I would tend to agree, but it comes with a cost in terms of complexity and state management. For simple setups like this, I still prefer the Serverless framework.

We add some basic configuration to our serverless.yml file:

 

// serverless.yml
service: myservice

provider:
  name: aws
  region: eu-west-2
  httpApi:
    payload: "2.0"
  lambdaHashingVersion: 20201221

functions:
  api:
    runtime: provided.al2
    package:
      artifact: dist/MyApi.zip
      individually: true
    handler: required-but-ignored
    events:
      - httpApi: "*"

 

 

Even though we are using AspNetCore, a Lambda is really just a function. AWS therefore requires an API Gateway in front of it. Serverless takes care of this for us. The combination of httpApi and 2.0 here means that we will use the new HTTP trigger of the API Gateway. This would be my preferred choice, as long as we don’t need some of the functionality still only present in the older REST trigger.

 

runtime: provided.al2 means we will use the custom runtime based on Amazon Linux 2.

 

Now we are finally ready to deploy our Lambda!

npx serverless@^2.70 deploy

 

The output should look something like this:

 

...
endpoints:
  ANY - https://ynop5r4gx2.execute-api.eu-west-2.amazonaws.com
...

 

Here you’ll find the URL where our Lambda can be reached. Let’s call this <YourUrl>.

Calling the Lambda

 

Using curl:
curl "https://<YourUrl>/graphql?query=%7B+sysInfo+%7D"

 

You should see a response similar to:

{ "data": { "sysInfo":".NET 6.0.1 running on amzn.2-x64" } }

Cleaning up

 

Unless you want to keep our Lambda running, you can remove all deployed AWS resources with:
npx serverless@^2.70 remove

 

Take me to the summary!

 

Bonus: Running on ARM

 

AWS recently announced the possibility to run Lambda on the new ARM-based Graviton2 CPU. It’s marketed as faster and cheaper. Note that ARM-based Lambdas are not yet available in all AWS regions and that they might not work with pre-compiled x86/x64 dependencies.

If we want to run on Graviton2 a few small changes are necessary:

  • Compiling for ARM
  • Configuring Lambda for ARM
  • Add additional packages for ARM

 

Compiling for ARM

 

Here we need to add our runtime target for the dotnet lambda tool to pick up:

 

// aws-lambda-tools-defaults.json
{
  "msbuild-parameters":
    "--self-contained true --runtime linux-arm64"
}

Configure Lambda for ARM

 

We need to specify the architecture of the Lambda function:

 

// serverless.yml
functions:
  api:
    ...
    architecture: arm64
    ...

Adding additional packages for ARM

 

According to this GitHub issue we need to add and configure an additional package when running a custom runtime on ARM:

 

// MyApi.csproj
...
<ItemGroup>
  <RuntimeHostConfigurationOption
    Include="System.Globalization.AppLocalIcu"
    Value="68.2.0.9"/>
  <PackageReference
    Include="Microsoft.ICU.ICU4C.Runtime"
    Version="68.2.0.9"/>
</ItemGroup>
...

 

When adding this the API stops working on non-ARM platforms though. A more portable solution is to use a condition on the ItemGroup, like this:

 

// MyApi.csproj
...
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-arm64'">
  <RuntimeHostConfigurationOption
    Include="System.Globalization.AppLocalIcu"
    Value="68.2.0.9"/>
  <PackageReference
    Include="Microsoft.ICU.ICU4C.Runtime"
    Version="68.2.0.9"/>
</ItemGroup>
...

Building, deploying, and calling it once more

 

Build and deploy as before.

Call the Lambda as before.

 

You should see a response similar to:

 

{ "data": { "sysInfo":".NET 6.0.1 running on amzn.2-arm64" } }

 

confirming that we are now running on ARM!

 

Clean up as before.

Summary

 

That’s it! We have now deployed a minimal serverless GraphQL API in .NET 6 on AWS Lambda. Full working code is available at GitHub.

Opinionated take aways:

  • Use GraphQL for most APIs
  • Use Hot Chocolate for GraphQL on .NET
  • Use Lambda for entire APIs, not just simple functions
  • Use dotnet lambda cli tool for packaging
  • Use Amazon.Lambda.AspNetCoreServer.Hosting for custom runtimes
  • Use a simple bootstrap script to start the API
  • Use Serverless framework for deployment
  • Use ARM if you can

 

Any comments or questions are welcome!

Frilanskonsult Magnus
Author – Magnus Markling, Freelance Cloud Architect

Vill du veta mer om oss på Developers Bay?