В предыдущем посте мы реализовали лямбда-функцию aws на основе Java и развернули ее с помощью CloudFront. Поскольку у нас настроена лямбда-функция, мы интегрируем ее с конечной точкой http с помощью AWS API Gateway .
Amazon API Gateway — это полностью управляемый сервис, который позволяет разработчикам легко создавать, публиковать, поддерживать, отслеживать и защищать API-интерфейсы в любом масштабе. С помощью нескольких щелчков мыши в Консоли управления AWS вы можете создать API, который выступает в роли «входной двери» для приложений, обеспечивающих доступ к данным, бизнес-логике или функциональным возможностям из ваших внутренних служб, таких как рабочие нагрузки, выполняемые в Amazon Elastic Compute Cloud. (Amazon EC2), код, работающий на AWS Lambda, или любое веб-приложение
Для этого примера представьте шлюз API, как если бы он был соединителем HTTP. Мы изменим нашу первоначальную функцию, чтобы реализовать разделение.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
package com.gkatzioura.deployment.lambda;import com.amazonaws.services.lambda.runtime.Context;import com.amazonaws.services.lambda.runtime.RequestHandler;import java.math.BigDecimal;import java.util.Map;import java.util.logging.Logger;/** * Created by gkatzioura on 9/10/2016. */public class RequestFunctionHandler implements RequestHandler<Map<String,String>,String> { private static final String NUMERATOR_KEY = "numerator"; private static final String DENOMINATOR_KEY = "denominator"; private static final Logger LOGGER = Logger.getLogger(RequestFunctionHandler.class.getName()); public String handleRequest(Map <String,String> values, Context context) { LOGGER.info("Handling request"); if(!values.containsKey(NUMERATOR_KEY)||!values.containsKey(DENOMINATOR_KEY)) { return "You need both numberator and denominator"; } try { BigDecimal numerator = new BigDecimal(values.get(NUMERATOR_KEY)); BigDecimal denominator= new BigDecimal(values.get(DENOMINATOR_KEY)); return numerator.divide(denominator).toString(); } catch (Exception e) { return "Please provide valid values"; } }} |
Затем мы изменим наш лямбда-код и обновим его на s3.
|
1
|
aws s3 cp build/distributions/JavaLambdaDeployment.zip s3://lambda-functions/JavaLambdaDeployment.zip |
Следующим шагом является обновление нашего шаблона CloudFormation и добавление запросов перенаправления шлюза API в нашу функцию lambda.
Сначала мы должны объявить наш отдых API
|
1
2
3
4
|
"AGRA16PAA": { "Type": "AWS::ApiGateway::RestApi", "Properties": {"Name": "CalculationApi"} } |
Затем нам нужно добавить ресурс отдыха. Внутри элемента DependsOn мы можем видеть id нашего остальных API. Поэтому cloudwatch создаст ресурс после того, как остальные API будут созданы.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
"AGR2JDQ8": { "Type": "AWS::ApiGateway::Resource", "Properties": { "RestApiId": {"Ref": "AGRA16PAA"}, "ParentId": { "Fn::GetAtt": ["AGRA16PAA","RootResourceId"] }, "PathPart": "divide" }, "DependsOn": [ "AGRA16PAA" ] } |
Другой важной частью является добавление разрешения, чтобы иметь возможность вызывать нашу лямбда-функцию.
|
01
02
03
04
05
06
07
08
09
10
11
|
"LPI6K5": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:invokeFunction", "FunctionName": {"Fn::GetAtt": ["LF9MBL", "Arn"]}, "Principal": "apigateway.amazonaws.com", "SourceArn": {"Fn::Join": ["", ["arn:aws:execute-api:", {"Ref": "AWS::Region"}, ":", {"Ref": "AWS::AccountId"}, ":", {"Ref": "AGRA16PAA"}, "/*"] ]} } } |
Последним шагом будет добавление метода шлюза api, чтобы иметь возможность вызывать нашу лямбда-функцию из шлюза api. Кроме того, мы добавим инструкцию по развертыванию шлюза API.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
"Deployment": { "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { "Ref": "AGRA16PAA" }, "Description": "First Deployment", "StageName": "StagingStage" }, "DependsOn" : ["AGM25KFD"] }, "AGM25KFD": { "Type": "AWS::ApiGateway::Method", "Properties": { "AuthorizationType": "NONE", "HttpMethod": "POST", "ResourceId": {"Ref": "AGR2JDQ8"}, "RestApiId": {"Ref": "AGRA16PAA"}, "Integration": { "Type": "AWS", "IntegrationHttpMethod": "POST", "IntegrationResponses": [{"StatusCode": 200}], "Uri": { "Fn::Join": [ "", [ "arn:aws:apigateway:", {"Ref": "AWS::Region"}, ":lambda:path/2015-03-31/functions/", {"Fn::GetAtt": ["LF9MBL", "Arn"]}, "/invocations" ] ] } }, "MethodResponses": [{ "StatusCode": 200 }] } |
Итак, мы закончили с нашей новой конфигурацией cloudwatch.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
{ "AWSTemplateFormatVersion": "2010-09-09", "Resources": { "LF9MBL": { "Type": "AWS::Lambda::Function", "Properties": { "Code": { "S3Bucket": "lambda-functions", "S3Key": "JavaLambdaDeployment.zip" }, "FunctionName": "SimpleRequest", "Handler": "com.gkatzioura.deployment.lambda.RequestFunctionHandler", "MemorySize": 128, "Role": "arn:aws:iam::274402012893:role/lambda_basic_execution", "Runtime": "java8" } }, "Deployment": { "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { "Ref": "AGRA16PAA" }, "Description": "First Deployment", "StageName": "StagingStage" }, "DependsOn" : ["AGM25KFD"] }, "AGM25KFD": { "Type": "AWS::ApiGateway::Method", "Properties": { "AuthorizationType": "NONE", "HttpMethod": "POST", "ResourceId": {"Ref": "AGR2JDQ8"}, "RestApiId": {"Ref": "AGRA16PAA"}, "Integration": { "Type": "AWS", "IntegrationHttpMethod": "POST", "IntegrationResponses": [{"StatusCode": 200}], "Uri": { "Fn::Join": [ "", [ "arn:aws:apigateway:", {"Ref": "AWS::Region"}, ":lambda:path/2015-03-31/functions/", {"Fn::GetAtt": ["LF9MBL","Arn"]}, "/invocations" ] ] } }, "MethodResponses": [{"StatusCode": 200}] }, "DependsOn": ["LF9MBL","AGR2JDQ8","LPI6K5"] }, "AGR2JDQ8": { "Type": "AWS::ApiGateway::Resource", "Properties": { "RestApiId": {"Ref": "AGRA16PAA"}, "ParentId": { "Fn::GetAtt": ["AGRA16PAA","RootResourceId"] }, "PathPart": "divide" }, "DependsOn": ["AGRA16PAA"] }, "AGRA16PAA": { "Type": "AWS::ApiGateway::RestApi", "Properties": { "Name": "CalculationApi" } }, "LPI6K5": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:invokeFunction", "FunctionName": {"Fn::GetAtt": ["LF9MBL", "Arn"]}, "Principal": "apigateway.amazonaws.com", "SourceArn": {"Fn::Join": ["", ["arn:aws:execute-api:", {"Ref": "AWS::Region"}, ":", {"Ref": "AWS::AccountId"}, ":", {"Ref": "AGRA16PAA"}, "/*"] ]} } } }} |
И последнее, но не менее важное: мы должны обновить наш предыдущий стек облачной информации.
Итак, мы загрузили наш последний шаблон
|
1
|
aws s3 cp cloudformationjavalambda2.template s3://cloudformation-templates/cloudformationjavalambda2.template |
И все, что нам нужно сделать, это обновить наш стек.
|
1
|
aws cloudformation update-stack --stack-name JavaLambdaStack --template-url https://s3.amazonaws.com/cloudformation-templates/cloudformationjavalambda2.template |
Наш стек только что обновился.
Мы можем добраться до нашей конечной точки шлюза API и попытаться выпустить сообщение.
|
1
2
|
curl -H "Content-Type: application/json" -X POST -d '{"numerator":1,"denominator":"2"}' https://{you api gateway endpoint}/StagingStage/divide"0.5" |
Вы можете найти исходный код на github .
| Ссылка: | Java в облаке AWS с использованием Lambda, Api Gateway и CloudFormation от нашего партнера по JCG Эммануила Гкациоураса из блога gkatzioura . |