{{announcement.body}}
{{announcement.title}}

AWS Lambda With MySQL (RDS) and API Gateway

DZone 's Guide to

AWS Lambda With MySQL (RDS) and API Gateway

In this article, we discuss the limitations of Lambda and how to design simple micro-service using AWS API gateway, and RDS.

· Cloud Zone ·
Free Resource

AWS and application architecture

AWS and application architecture

I have been working on Lambda for some projects, and recently, I had to design and write an FAS service using Lambda functions and read/write data into RDS (MySQL). I'm sharing what I've learned here.

Before We Begin

Prerequisites

This tutorial assumes that you have some knowledge of basic Lambda operations and the AWS console, RDS, IAM, and Node.js.

To understand whether a serverless application is good for you or not, you need to understand the limitations of Lambda, what a cold start is, and how concurrency works in Lambda. The Lambda execution model is, of course, a different architecture than traditional web applications in Spring.

What Is a Cold Start?

When a user starts their first request, Lambda has a slight delay while it spins up a new container and loads our code and dependencies in memory. This is called a cold start. A cold start only happens if there is no idle container available or waiting to run our code. Once a connection is timed out, AWS kills the container, and future requests will again spin up a new container. The first request will always be a bit slower due to the cold start, but subsequent requests will hit the same instance quickly.

You may also enjoy: Querying RDS MySQL DB With NodeJS Lambda Function

We can use a Cloud Watch Timer/dummy request to keep lambdas warm.

Concurrency

Concurrent requests will trigger the creation of new AWS Lambda instances. For example, if you have five concurrent requests to the same Lambda function, AWS will create five containers to serve the requests. In short, when you first invoke a function, AWS Lambda creates an instance of the function and runs its handler method to process the event. If you invoke the function again while the first event is being processed, Lambda creates another instance.

You can configure a function with reserved concurrency to guarantee that it can always reach a certain level of concurrency. This function can run with this maximum amount of concurrency without interrupting or waiting.

The Lambda currency limit is 1000 by default. Take note that one Lambda function that has scaled up can hit the performance of every other Lambda function in the same region.

Concurrency

Concurrency

Reserve concurrency doesn't start until 20 instances on the first Lambda call. Its reserve capacity for a function can scale up or down. As soon as the concurrent executions limit is reached, the next execution gets throttled. 

Retry Behavior

Lambda functions will retry three times before they fail due to an uncaught application error. If you added context.succeed and did not handle exceptions properly, Lambda will not retry the function and instead, will assume that the function was successful. If you have added context.fail, Lambda will retry the function.

JavaScript




x
11


 
1
module.exports.handler(event, context, callback) {
2
  try {  
3
     // Do you what you want to do.  
4
      return callback(null, 'Success') 
5
 } catch (err) { 
6
     // You probably still want to log it. 
7
     console.error(err) 
8
     // Return fail. 
9
     return callback(null, 'fail') 
10
  }
11
 }



Common Invocation Errors

  • Request – The request event is too large or isn't valid JSON, the function doesn't exist, or a parameter value is of the wrong type.
  • Caller – The user or service doesn't have permission to invoke the function.
  • Account – The maximum number of function instances are already running or requests are being made too quickly.

Debug Lambda

The following are two approaches to debug Lambda on a local machine:

    1. Choose Test at the top right of your Lambda function to bring up a screen that allows you to                      configure a new test that can be run to verify success/failure and you can also add console.log for              debugging.

    2. Another most popular option is Cloudwatch for debugging on Aws console .When you review                  CloudWatch log files or metrics when you're troubleshooting errors, be aware that they are                        displayed or stored in the Region closest to the location where the function executed.

Lambda-local lets you test Amazon Lambda functions on your local machine, by providing a simplistic API and command-line tool.

Shell




xxxxxxxxxx
1


1
npm install -g lambda-local 



You can use Lambda-local as a command line tool.

Shell




xxxxxxxxxx
1


1
# Simple usage  lambda-local -l index.js -h handler -e examples/s3-put.js  
2
# Input environment variables  lambda-local -l index.js -h handler -e examples/s3-put.js -E '{"key":"value","key2":"value2"}'  



You can find further information from the following link:

You can also use SAM Local to develop and test Lambda functions locally with Docker.

You can find further information on following link

Lambda Functions Versioning and Deployment

If you want to publish a new version of a function for QA testing without affecting the stable production version, then you can use Lambda version option. When you choose a new version, the system creates a new version of your Lambda function each time that you publish the function. We can publish multiple versions of a function. Each version can be invoked in parallel in a separate container. By default, the version would be $LATEST.

Choosing version

Choosing version

We can configure blue-green /canary deployment for continuous delivery:

Configure RDS 

The first step to start code is to provision an RDS instance using AWS Console. Then, try AWS Free Tier with Amazon RDS. 

MySQL 750 hours of Amazon RDS Single-AZ db.t2.micro Instance usage running MySQL 20 GB of General Purpose (SSD) DB Storage and 20 GB of backup storage for your automated database backups and any user-initiated DB Snapshots

Write Your First Lambda Function

When you invoke a function, you can choose to invoke it synchronously or asynchronously. With synchronous invocation, you wait for the function to process the event and return a response. With asynchronous invocation, Lambda queues the event for processing and returns a response immediately. For asynchronous invocation, Lambda handles retries and can send failed events to a dead-letter queue.

You need to create a role for Lambda. As a best practice, define policies that follow the principle of granting least privilege. In other words, the policies include only the permissions that users require to perform their tasks, for learning purpose adding broad role but you can narrow as per your requirements.

AmazonRDSFullAccess

JSON




xxxxxxxxxx
1
53


 
1
2
   "Version":"2012-10-17",
3
   "Statement":[ 
4
      { 
5
         "Action":[ 
6
            "rds:*",
7
            "application-autoscaling:DeleteScalingPolicy",
8
            "application-autoscaling:DeregisterScalableTarget",
9
            "application-autoscaling:DescribeScalableTargets",
10
            "application-autoscaling:DescribeScalingActivities",
11
            "application-autoscaling:DescribeScalingPolicies",
12
            "application-autoscaling:PutScalingPolicy",
13
            "application-autoscaling:RegisterScalableTarget",
14
            "cloudwatch:DescribeAlarms",
15
            "cloudwatch:GetMetricStatistics",
16
            "cloudwatch:PutMetricAlarm",
17
            "cloudwatch:DeleteAlarms",
18
            "ec2:DescribeAccountAttributes",
19
            "ec2:DescribeAvailabilityZones",
20
            "ec2:DescribeInternetGateways",
21
            "ec2:DescribeSecurityGroups",
22
            "ec2:DescribeSubnets",
23
            "ec2:DescribeVpcAttribute",
24
            "ec2:DescribeVpcs",
25
            "sns:ListSubscriptions",
26
            "sns:ListTopics",
27
            "sns:Publish",
28
            "logs:DescribeLogStreams",
29
            "logs:GetLogEvents"
30
         ],
31
         "Effect":"Allow",
32
         "Resource":"*"
33
      },
34
      { 
35
         "Action":"pi:*",
36
         "Effect":"Allow",
37
         "Resource":"arn:aws:pi:*:*:metrics/rds/*"
38
      },
39
      { 
40
         "Action":"iam:CreateServiceLinkedRole",
41
         "Effect":"Allow",
42
         "Resource":"*",
43
         "Condition":{ 
44
            "StringLike":{ 
45
               "iam:AWSServiceName":[ 
46
                  "rds.amazonaws.com",
47
                  "rds.application-autoscaling.amazonaws.com"
48
               ]
49
            }
50
         }
51
      }
52
   ]
53
}



AmazonVPCFullAccess

JSON




xxxxxxxxxx
1
152


 
1
2
   "Version":"2012-10-17",
3
   "Statement":[ 
4
      { 
5
         "Effect":"Allow",
6
         "Action":[ 
7
            "ec2:AcceptVpcPeeringConnection",
8
            "ec2:AcceptVpcEndpointConnections",
9
            "ec2:AllocateAddress",
10
            "ec2:AssignIpv6Addresses",
11
            "ec2:AssignPrivateIpAddresses",
12
            "ec2:AssociateAddress",
13
            "ec2:AssociateDhcpOptions",
14
            "ec2:AssociateRouteTable",
15
            "ec2:AssociateSubnetCidrBlock",
16
            "ec2:AssociateVpcCidrBlock",
17
            "ec2:AttachClassicLinkVpc",
18
            "ec2:AttachInternetGateway",
19
            "ec2:AttachNetworkInterface",
20
            "ec2:AttachVpnGateway",
21
            "ec2:AuthorizeSecurityGroupEgress",
22
            "ec2:AuthorizeSecurityGroupIngress",
23
            "ec2:CreateCustomerGateway",
24
            "ec2:CreateDefaultSubnet",
25
            "ec2:CreateDefaultVpc",
26
            "ec2:CreateDhcpOptions",
27
            "ec2:CreateEgressOnlyInternetGateway",
28
            "ec2:CreateFlowLogs",
29
            "ec2:CreateInternetGateway",
30
            "ec2:CreateNatGateway",
31
            "ec2:CreateNetworkAcl",
32
            "ec2:CreateNetworkAcl",
33
            "ec2:CreateNetworkAclEntry",
34
            "ec2:CreateNetworkInterface",
35
            "ec2:CreateNetworkInterfacePermission",
36
            "ec2:CreateRoute",
37
            "ec2:CreateRouteTable",
38
            "ec2:CreateSecurityGroup",
39
            "ec2:CreateSubnet",
40
            "ec2:CreateTags",
41
            "ec2:CreateVpc",
42
            "ec2:CreateVpcEndpoint",
43
            "ec2:CreateVpcEndpointConnectionNotification",
44
            "ec2:CreateVpcEndpointServiceConfiguration",
45
            "ec2:CreateVpcPeeringConnection",
46
            "ec2:CreateVpnConnection",
47
            "ec2:CreateVpnConnectionRoute",
48
            "ec2:CreateVpnGateway",
49
            "ec2:DeleteCustomerGateway",
50
            "ec2:DeleteDhcpOptions",
51
            "ec2:DeleteEgressOnlyInternetGateway",
52
            "ec2:DeleteFlowLogs",
53
            "ec2:DeleteInternetGateway",
54
            "ec2:DeleteNatGateway",
55
            "ec2:DeleteNetworkAcl",
56
            "ec2:DeleteNetworkAclEntry",
57
            "ec2:DeleteNetworkInterface",
58
            "ec2:DeleteNetworkInterfacePermission",
59
            "ec2:DeleteRoute",
60
            "ec2:DeleteRouteTable",
61
            "ec2:DeleteSecurityGroup",
62
            "ec2:DeleteSubnet",
63
            "ec2:DeleteTags",
64
            "ec2:DeleteVpc",
65
            "ec2:DeleteVpcEndpoints",
66
            "ec2:DeleteVpcEndpointConnectionNotifications",
67
            "ec2:DeleteVpcEndpointServiceConfigurations",
68
            "ec2:DeleteVpcPeeringConnection",
69
            "ec2:DeleteVpnConnection",
70
            "ec2:DeleteVpnConnectionRoute",
71
            "ec2:DeleteVpnGateway",
72
            "ec2:DescribeAccountAttributes",
73
            "ec2:DescribeAddresses",
74
            "ec2:DescribeAvailabilityZones",
75
            "ec2:DescribeClassicLinkInstances",
76
            "ec2:DescribeCustomerGateways",
77
            "ec2:DescribeDhcpOptions",
78
            "ec2:DescribeEgressOnlyInternetGateways",
79
            "ec2:DescribeFlowLogs",
80
            "ec2:DescribeInstances",
81
            "ec2:DescribeInternetGateways",
82
            "ec2:DescribeKeyPairs",
83
            "ec2:DescribeMovingAddresses",
84
            "ec2:DescribeNatGateways",
85
            "ec2:DescribeNetworkAcls",
86
            "ec2:DescribeNetworkInterfaceAttribute",
87
            "ec2:DescribeNetworkInterfacePermissions",
88
            "ec2:DescribeNetworkInterfaces",
89
            "ec2:DescribePrefixLists",
90
            "ec2:DescribeRouteTables",
91
            "ec2:DescribeSecurityGroupReferences",
92
            "ec2:DescribeSecurityGroups",
93
            "ec2:DescribeStaleSecurityGroups",
94
            "ec2:DescribeSubnets",
95
            "ec2:DescribeTags",
96
            "ec2:DescribeVpcAttribute",
97
            "ec2:DescribeVpcClassicLink",
98
            "ec2:DescribeVpcClassicLinkDnsSupport",
99
            "ec2:DescribeVpcEndpointConnectionNotifications",
100
            "ec2:DescribeVpcEndpointConnections",
101
            "ec2:DescribeVpcEndpoints",
102
            "ec2:DescribeVpcEndpointServiceConfigurations",
103
            "ec2:DescribeVpcEndpointServicePermissions",
104
            "ec2:DescribeVpcEndpointServices",
105
            "ec2:DescribeVpcPeeringConnections",
106
            "ec2:DescribeVpcs",
107
            "ec2:DescribeVpnConnections",
108
            "ec2:DescribeVpnGateways",
109
            "ec2:DetachClassicLinkVpc",
110
            "ec2:DetachInternetGateway",
111
            "ec2:DetachNetworkInterface",
112
            "ec2:DetachVpnGateway",
113
            "ec2:DisableVgwRoutePropagation",
114
            "ec2:DisableVpcClassicLink",
115
            "ec2:DisableVpcClassicLinkDnsSupport",
116
            "ec2:DisassociateAddress",
117
            "ec2:DisassociateRouteTable",
118
            "ec2:DisassociateSubnetCidrBlock",
119
            "ec2:DisassociateVpcCidrBlock",
120
            "ec2:EnableVgwRoutePropagation",
121
            "ec2:EnableVpcClassicLink",
122
            "ec2:EnableVpcClassicLinkDnsSupport",
123
            "ec2:ModifyNetworkInterfaceAttribute",
124
            "ec2:ModifySubnetAttribute",
125
            "ec2:ModifyVpcAttribute",
126
            "ec2:ModifyVpcEndpoint",
127
            "ec2:ModifyVpcEndpointConnectionNotification",
128
            "ec2:ModifyVpcEndpointServiceConfiguration",
129
            "ec2:ModifyVpcEndpointServicePermissions",
130
            "ec2:ModifyVpcPeeringConnectionOptions",
131
            "ec2:ModifyVpcTenancy",
132
            "ec2:MoveAddressToVpc",
133
            "ec2:RejectVpcEndpointConnections",
134
            "ec2:RejectVpcPeeringConnection",
135
            "ec2:ReleaseAddress",
136
            "ec2:ReplaceNetworkAclAssociation",
137
            "ec2:ReplaceNetworkAclEntry",
138
            "ec2:ReplaceRoute",
139
            "ec2:ReplaceRouteTableAssociation",
140
            "ec2:ResetNetworkInterfaceAttribute",
141
            "ec2:RestoreAddressToClassic",
142
            "ec2:RevokeSecurityGroupEgress",
143
            "ec2:RevokeSecurityGroupIngress",
144
            "ec2:UnassignIpv6Addresses",
145
            "ec2:UnassignPrivateIpAddresses",
146
            "ec2:UpdateSecurityGroupRuleDescriptionsEgress",
147
            "ec2:UpdateSecurityGroupRuleDescriptionsIngress"
148
         ],
149
         "Resource":"*"
150
      }
151
   ]
152
}



AWSLambdaVPCAccessExecutionRole

JSON




xxxxxxxxxx
1
17


 
1
2
   "Version":"2012-10-17",
3
   "Statement":[ 
4
      { 
5
         "Effect":"Allow",
6
         "Action":[ 
7
            "logs:CreateLogGroup",
8
            "logs:CreateLogStream",
9
            "logs:PutLogEvents",
10
            "ec2:CreateNetworkInterface",
11
            "ec2:DescribeNetworkInterfaces",
12
            "ec2:DeleteNetworkInterface"
13
         ],
14
         "Resource":"*"
15
      }
16
   ]
17
}



permission policies

Permission policies

To create a Lambda function, go to AWS Console and select Lambda.

Creating a Lambda function

Creating a Lambda function

Click create function and choose Node.js 12.x. Then, choose existing role we created above.

creating a function

In order to support a MySQL dependency, we need to create code first on your local computer and then upload it to the Lambda console.

Create a folder and create package.json

Shell




xxxxxxxxxx
1


 
1
npm init


creating package.json file

Creating package.json file

Once the file is created, you can find the following JSON in the folder.

JSON




xxxxxxxxxx
1
11


 
1
2
   "name":"test",
3
   "version":"1.0.0",
4
   "description":"test",
5
   "main":"index.js",
6
   "scripts":{ 
7
      "test":"echo \"Error: no test specified\" && exit 1"
8
   },
9
   "author":"Vaquar khan",
10
   "license":"ISC"
11
}



You need to add MYSQL node dependency in project using following command

Shell




xxxxxxxxxx
1


1
npm install --save mysql 



Now, add a handler into the app, create index.js (index.handler), and add Lambda logic.

In Lambda, first, we are going to create a connection object and then call our database.

JavaScript




xxxxxxxxxx
1
18


 
1
const mysql = require('mysql'); 
2
 
          
3
const connection = mysql.createConnection({ 
4
 //following param coming from aws lambda env variable 
5
  host: process.env.RDS_LAMBDA_HOSTNAME,  
6
  user: process.env.RDS_LAMBDA_USERNAME, 
7
  password: process.env.RDS_LAMBDA_PASSWORD, 
8
  port: process.env.RDS_LAMBDA_PORT, 
9
  // calling direct inside code  
10
  connectionLimit: 10,   
11
  multipleStatements: true,
12
 // Prevent nested sql statements 
13
  connectionLimit: 1000,   
14
connectTimeout: 60 * 60 * 1000, 
15
  acquireTimeout: 60 * 60 * 1000, 
16
  timeout: 60 * 60 * 1000, 
17
  debug: true 
18
});



Then, we need to call our Lambda handler.

JavaScript




xxxxxxxxxx
1
30


 
1
exports.handler = async (event) => { 
2
  try {    
3
 const data = await new Promise((resolve, reject) => {
4
       connection.connect(function (err) {   
5
      if (err) {      
6
     reject(err);     
7
    }        
8
 connection.query('CREATE DATABASE testdb', function (err, result) {  
9
         if (err) {  
10
           console.log("Error->" + err);     
11
        reject(err);        
12
   }         
13
  resolve(result);  
14
       });     
15
  })  
16
   }); 
17
 
          
18
    return { 
19
      statusCode: 200,  
20
     body: JSON.stringify(data)   
21
  } 
22
 
          
23
  } catch (err) {    
24
 return {   
25
    statusCode: 400,   
26
    body: err.message 
27
    } 
28
  }
29
 }; 
30
 
          



Now, create a zip file and upload it.

uploading zip file

Uploading zip file


After this, upload and click on index.js. For further changes, use inline editor.

using inline editor

Using inline editor

Create a lambda env variable with its key-value pairs. 

Java




xxxxxxxxxx
1


1
 RDS_LAMBDA_HOSTNAME 
2
 RDS_LAMBDA_USERNAME 
3
 RDS_LAMBDA_PASSWORD 
4
 RDS_LAMBDA_PORT



Now, configure Lambda with RDS and VPC,  go to the Security group of the RDS instance. After selecting the default security group,  click on it. On the EC2 page, scroll down to find inbound and outbound settings.

In inbound settings, click edit. You can change the IP here.

  • 0.0.0.0/0 — this makes RDS open to the world and is not recommended.
  • Configure VPC inside the Lambda function network to Lambda function work. First, go to the Lambda function, click on Network, and then select the VPC and copy the IP address. If no VPC is selected, select a VPC that's the as the DB function and copy the IP address. Add this IP in RDS inbound settings.

Asynch-rds-create-table

Asych RDS create table

Save it and test your Lambda function.

Results

RDS output

RDS output

The following are a few Lambda handlers to understand how CRUD operations work in Lambda.

Create a database using lambda

JavaScript




xxxxxxxxxx
1
46


 
1
const mysql = require('mysql'); 
2
 
          
3
const connection = mysql.createConnection({ 
4
 //following param coming from aws lambda env variable  
5
 
          
6
 host: process.env.RDS_LAMBDA_HOSTNAME,
7
  user: process.env.RDS_LAMBDA_USERNAME,
8
  password: process.env.RDS_LAMBDA_PASSWORD, 
9
  port: process.env.RDS_LAMBDA_PORT, 
10
 // calling direct inside code 
11
  connectionLimit: 10,  
12
 multipleStatements: true,
13
// Prevent nested sql statements 
14
  connectionLimit: 1000, 
15
  connectTimeout: 60 * 60 * 1000,
16
   acquireTimeout: 60 * 60 * 1000,  
17
 timeout: 60 * 60 * 1000,  
18
 debug: true 
19
}); exports.handler = async (event) => {  
20
 try {    
21
 const data = await new Promise((resolve, reject) => {  
22
     connection.connect(function (err) {  
23
       if (err) {    
24
       reject(err);
25
         }      
26
   connection.query('CREATE DATABASE testdb',
27
 function (err, result) {  
28
         if (err) {  
29
           console.log("Error->" + err);      
30
       reject(err);        
31
   }           resolve(result);  
32
       });     
33
  })   
34
  }); 
35
 
          
36
    return {  
37
     statusCode: 200,   
38
    body: JSON.stringify(data)  
39
   } 
40
 
          
41
  } catch (err) {
42
     return {   
43
    statusCode: 400, 
44
      body: err.message   
45
  }  
46
 } }; 



Create a table using lambda   

JavaScript




xxxxxxxxxx
1
57


 
1
exports.handler = async (event) => {   
2
const sql = "CREATE TABLE MESSAGE (message VARCHAR(255))";  
3
 con.query(sql, function (err, result) {   
4
  if (err) throw err;  
5
   console.log("Table created");  
6
 });   
7
return "Table Created" 
8
}; 
9
 
          
10
const mysql = require('mysql'); 
11
 
          
12
const connection = mysql.createConnection({ 
13
 //following param coming from aws lambda env variable  
14
  host: process.env.RDS_LAMBDA_HOSTNAME, 
15
  user: process.env.RDS_LAMBDA_USERNAME,  
16
  password: process.env.RDS_LAMBDA_PASSWORD, 
17
  port: process.env.RDS_LAMBDA_PORT, 
18
 // calling direct inside code
19
  connectionLimit: 10,   
20
  multipleStatements: true,
21
  // Prevent nested sql statements   
22
  connectionLimit: 1000, 
23
  connectTimeout: 60 * 60 * 1000, 
24
  acquireTimeout: 60 * 60 * 1000,
25
  timeout: 60 * 60 * 1000,
26
   debug: true 
27
}); exports.handler = async (event) => { 
28
  try {    
29
 const data = await new Promise((resolve, reject) => { 
30
      connection.connect(function (err) {     
31
    if (err) {       
32
    reject(err);    
33
     }      
34
   connection.query('CREATE TABLE Employee (message VARCHAR(255))', 
35
function  (err, result) { 
36
          if (err) {    
37
         console.log("Error->" + err);  
38
         reject(err);
39
      }
40
           resolve(result);        
41
    });     
42
   })    
43
 }); 
44
 
          
45
    return {   
46
    statusCode: 200, 
47
      body: JSON.stringify(data)   
48
  } 
49
 
          
50
  } catch (err) {   
51
  return {    
52
   statusCode: 400,    
53
   body: err.message 
54
    }  
55
 }
56
 }; 
57
 
          


   

Insert records using lambda

JavaScript




xxxxxxxxxx
1
12


 
1
exports.handler = (event, context, callback) => {  
2
 // allows for using callbacks as finish/error-handlers  
3
 context.callbackWaitsForEmptyEventLoop = false;  
4
 const sql = "insert into testdb.Employee values(1,'Vaquar khan');";  
5
 con.query(sql, (err, res) => { 
6
    if (err) {   
7
    throw err   
8
  }     
9
callback(null, '1 records inserted.');  
10
 }) 
11
}; 
12
 
          



Select records using lambda  

JavaScript




xxxxxxxxxx
1
10
9


 
1
exports.handler = (event, context, callback) => {   
2
// allows for using callbacks as finish/error-handlers   
3
context.callbackWaitsForEmptyEventLoop = false; 
4
const sql = "select * from testdb.Employee "; 
5
con.query(sql, function (err, result) {   
6
  if (err) throw err;     
7
  callback(null, result)  
8
 });
9
 }; 


 

Select records with criteria using lambda 

JavaScript




xxxxxxxxxx
1


 
1
exports.handler = (event, context, callback) => { 
2
  // allows for using callbacks as finish/error-handlers  
3
 context.callbackWaitsForEmptyEventLoop = false; 
4
 const sql = "select * from  testdb.Employee where emp_id = " + event.emp_id;  
5
 con.query(sql, function (err, result) { 
6
    if (err) throw err;     callback(null, result)  
7
 }); 
8
};

 


Final Project

Now, we're down to the actual meat-and-potatoes of what we're trying to do:

Create a Table

MySQL




xxxxxxxxxx
1


 
1
use testdb; 
2
 
          
3
CREATE TABLE `Employee` ( 
4
  `emp_id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
5
  `emp_name` varchar(100) DEFAULT NULL,      PRIMARY KEY (`emp_id`)    ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 
6
 
          
7
insert into Employee values(1,'Vaquar khan'); 
8
insert into Employee values(2,'Zidan khan'); 



Create a Lambda 

JavaScript




xxxxxxxxxx
1
28


 
1
const mysql = require('mysql'); 
2
 
          
3
const con = mysql.createConnection({ 
4
   host: process.env.LAMBDA_HOSTNAME,  
5
   user: process.env.LAMBDA_USERNAME,
6
   password: process.env.LAMBDA_PASSWORD, 
7
   port: process.env.LAMBDA_PORT,  
8
   connectionLimit: 10,  
9
   multipleStatements: true,
10
   // Prevent nested sql statements  
11
   connectionLimit: 1000, 
12
   connectTimeout: 60 * 60 * 1000, 
13
   acquireTimeout: 60 * 60 * 1000, 
14
   timeout: 60 * 60 * 1000,
15
   debug: true,  
16
   database:'testdb' 
17
}); 
18
 
          
19
exports.handler = (event, context, callback) => {  
20
   console.log('inside lambda...'+event.emp_id) 
21
  // allows for using callbacks as finish/error-handlers 
22
  context.callbackWaitsForEmptyEventLoop = false; 
23
  const sql = "select * from Employee where emp_id = " + event.emp_id;  
24
  con.query(sql, function (err, result) {   
25
  if (err) throw err; 
26
    callback(null, result)
27
   }); 
28
}; 


 

Create a Test Event

JSON




xxxxxxxxxx
1


 
1
{ "emp_id":1, "emp_name":"xyz" }



Create an API Gateway

The number of APIs per account limit is 600 regional APIs, 600 private APIs, and 120 edge APIs. Now, you can create and import regional and private APIs at a rate of one request every three seconds and deploy APIs at a rate of one request every five seconds.

Note, when you deploy an API to API Gateway, throttling is enabled by default in the stage configurations.

For the time being, in this tutorial, we are not implementing security on the API gateway, but it's mandatory to add security on gateway.

The following mechanisms can be used for authentication and authorization of the API gateway:


Create a Resource

creating a resource

Creating a resource

Create Method add GET

creating a method

Creating a method


adding GET

Adding GET


Deploy an API

Create a new stage and deploy the API. After successfully deploying, you can see the URL.

Test Lambda with API gateway

Download Postman or use the Postman Chrome extension to call the API.

Summary

In this post, we discussed how to create applications quickly to run in AWS Lambda, which provides low cost, zero maintenance compute, and automatically scales. We also discussed the limitations of Lambda and how to design simple micro-service using AWS API gateway, and RDS. In the next post, we will try to cover AWS Cognito for Authentication/Authorization and how to sync Cognito data into an RDS table.

Further Reading

Dealing With Serverless Cold Starts, Once and For All!

A Simple API Using AWS RDS, Lambda, and API Gateway

Topics:
aws lambda ,serverless architecture

Published at DZone with permission of Vaquar Khan . See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}