Showing posts with label python. Show all posts
Showing posts with label python. Show all posts

Monday, June 15, 2020

AWS Lambda - python and java

AWS Lambda

Overview

AWS Lambda is a serverless, automatically scaling component for handling requests from various sources. This computing service is very helpful to prepare data, check changed element on S3, etc.It also could work as an element to handle requests from web services. Below is prepared very simple solution which contains two AWS Lambda functions. First one (created in python) is responsible for logic. The second one (created in java) is called for calculate array's average value.  






The solution

AWS Lambda in python

I prepared python code with the logic. Function calculates internally sum of array's elements. If average function is selected then next one AWS Lambda is called. 


import logging
import boto3
import json
logger = logging.getLogger()
logger.setLevel(logging.INFO)
client = boto3.client('lambda')
def lambda_handler(event, context):
    logger.info("FrontFunction got event{}".format(event))
    operation = event['operation']
    listOfItems = event['listOfItems']
 
    arrayStr = []
 
    if (operation == 'avg'):
        for i in listOfItems:
            arrayStr.append(i)
        response = client.invoke(
            FunctionName="Java8Tutorial",
            InvocationType='RequestResponse',
            Payload=json.dumps({"queryParameters": {"listOfItems":arrayStr}})
        )
        response = json.loads(response['Payload'].read().decode("utf-8"))
    elif (operation == 'sum'):
        out = 0
        for i in listOfItems:
            logger.info(i)
            out += int(i)
        response = out 
    else:
        response = 'Not defined'
 
    logger.info(response)
    return response

GatewayAPI contains reference to this Lambda function.  

































CloudWatch component for monitoring is integrated with function's dashboard. 





























On the top toolbar is also available button to configure function throttling.   

GatewayAPI

Gateway API couples HTTP requests (methods: GET, PUT, POST, DELETE,.. )  with Lambda functions. My API is not protected because it is only for testing but it is a good practice to protect communication. Below we can see the HTTP mapping to the Lambda Function.  
























AWS Lambda in java

Second lambda is created in Java. Java works generally slower then Python and "coldstart" consume more time. We can see simple code for parse JSON and calculate average value.   


package com.amazonaws.lambda.java8tutorial;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.OptionalDouble;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.ParseException;
import org.json.simple.parser.JSONParser;
public class LambdaFunctionHandler implements RequestStreamHandler {
    @Override
    @SuppressWarnings("unchecked")
    public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
            LambdaLogger logger = context.getLogger();
        logger.log("Start ARTSCI: Java Lambda handler ");             
        BufferedReader reader = new BufferedReader(new InputStreamReader(input));
        JSONObject outJson = new JSONObject();     
        JSONArray arrayItems = new JSONArray();
        String outputString = "Array's avg value is ";
        try {
        JSONParser parser = new JSONParser();
            JSONObject event = (JSONObject)parser.parse(reader);
            if (event.get("queryParameters") != null) {
                JSONObject qps = (JSONObject)event.get("queryParameters");
                if ( qps.get("listOfItems") != null) {                                arrayItems = (JSONArray) qps.get("listOfItems");
                OptionalDouble avg = arrayItems.stream().mapToInt(str -> Integer.parseInt((String) str)).average();
                    outputString += avg.getAsDouble();
                }
            }
         
         
            JSONObject responseBody = new JSONObject();
            responseBody.put("message", outputString);
            outJson.put("body", responseBody);
         
        } catch(ParseException pex) {
        outJson.put("statusCode", "400");
        outJson.put("exception", pex);
        }
     
     
        logger.log(outJson.toJSONString());
        OutputStreamWriter writer = new OutputStreamWriter(output, "UTF-8");
        writer.write(outJson.toJSONString());
        writer.close();
    }
}

Very important is to change permissions to allow one Lambda function call another one Lambda function.  


















The Results

At the end it is necessary to test all functionality.

Calculation of AVG
C:\Users\Artur>curl --location --request GET https://[unique].execute-api.eu-central-1.amazonaws.com/dev?name=artsci --header "Content-Type: application/json" --data-raw "{\"operation\": \"avg\",\"listOfItems\": [\"1\",\"2\",\"3\",\"4\",\"5\",\"6\"]}"
{"body": {"message": "Array's avg value is 3.5"}}

Calculation of SUM
C:\Users\Artur>curl --location --request GET https://[unique].execute-api.eu-central-1.amazonaws.com/dev?name=artsci --header "Content-Type: application/json" --data-raw "{\"operation\": \"sum\",\"listOfItems\": [\"1\",\"2\",\"3\",\"4\",\"5\",\"6\"]}"
21