LoginSignup
2
0

サーバーレスアーキテクチャで翻訳 Web API を構築してみた【AWS Hands-on for Beginners Serverless #1】

Posted at

はじめに

AWS認定試験の勉強している時にサーバレスアーキテクチャに関する問題がたくさん出てきました。
なので復習もかねて、今回はAWS Hands-on for Beginners Serverless #1を参考に、サーバレスアーキテクチャを実際に構築していきたいと思います。

学習するサービス

  • AWS Lambda
  • Amazon API Gateway
  • Amazon DynamoDB
  • Amazon Translate

AWS Hands-on for Beginners Serverless #1の概要

このハンズオンでは、"こんにちは" と入力すると "Hello" と返すWebAPIを作成します。

構築する構成図は以下になります。
Hands-On-for-Beginners_2022_Serverless1_0819_v1.png
引用:AWS Hands-on for Beginners Serverless #1

作成するWebAPIリクエストの流れ

  1. API Gatewayがリクエストを受け取けつけるとLambdaを呼び出す。
  2. LambdaはTranslateを呼び出し翻訳結果を取得する。
  3. 翻訳結果をAPIGatewayに返しAPIレスポンスを返す。
  4. リクエストのinput、outputの履歴をDynamoDBに保存する。

このハンズオンは以下の構成になっております。

Session 分:秒
1 Serverless アーキテクチャの概要 09:54
2 AWS Lambda の概要 06:40
3 AWS Lambda ハンズオン① Lambda を単体で使ってみる 10:14
4 AWS Lambda ハンズオン② 他のサービスを呼び出してみる 07:41
5 Amazon API Gateway の概要 08:12
6 Amazon API Gateway ハンズオン① API Gateway を単体で使ってみる 06:14
7 Amazon API Gateway ハンズオン② API Gateway と Lambda を組み合わせる 10:20
8 Amazon DynamoDB の概要 07:44
9 Amazon DynamoDB ハンズオン①テーブルを作ってみる 04:41
10 Amaozn DynamoDB ハンズオン② API Gateway と Lambda と DynamoDB を組み合わせる 08:03

座学動画についてはこの記事では触れませんが、とても分かりやすいと思うので
気になった方はぜひAWS Hands-on for Beginners Serverless #1をご覧ください。

AWS Hands-on for Beginnersとは

AWS Hands-on for Beginnersとは、動画を見ながら実際にサービスを触って学習できるAWS公式提供の動画形式コンテンツです。

下図の右側にあるアンケートに答えると無償で視聴できます。
Screenshot 2023_08_04 23_26_46.png

ハンズオン実践

細かいやり方や設定については省略させていただきます。
詳細については、ハンズオン動画をご覧いただければと思います。

3. AWS Lambda ハンズオン① Lambda を単体で使ってみる

イベントの中身をログとして出力できるLambda関数を実装します。

1. Lambda関数「translate-function」を作成する。
2. イベント「Test」を作成し、テストを実行する。
3. イベントの中身をログとして出力するように、「translate-function」を実装する。
4. CloudWatchでログを確認し、きちんと出力されているか確認する。

以下のように実装しました。

lambda_function.py
import json
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):

    logger.info(event)
    
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

以下のテストイベントを実行します。

Test
{
  "key1": "value1",
  "key2": "value2",
  "key3": "value3"
}

無事にイベントの中身をログとして出力できています。

translate-function - Lambda - Google Chrome 2023_08_05 14_19_49.png

Function Log
START RequestId: b0a4fea6-e5dd-4fcc-9538-d576e1fcafd4 Version: $LATEST
[INFO]	2023-08-05T04:27:26.667Z	b0a4fea6-e5dd-4fcc-9538-d576e1fcafd4	{'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
END RequestId: b0a4fea6-e5dd-4fcc-9538-d576e1fcafd4
REPORT RequestId: b0a4fea6-e5dd-4fcc-9538-d576e1fcafd4	Duration: 2.08 ms	Billed Duration: 3 ms	Memory Size: 128 MB	Max Memory Used: 36 MB	Init Duration: 118.60 ms

CloudWatchでも、テストイベントの中身をログとして出力できました。
translate-function - Lambda - Google Chrome 2023_08_05 14_35_14.png

2023-08-05T13:27:26.544+09:00	INIT_START Runtime Version: python:3.7.v30 Runtime Version ARN: arn:aws:lambda:ap-northeast-1::runtime:898e3ea3957b56a1999758f7a44db46ffe42dc979b385666bf4950b8611ec475
2023-08-05T13:27:26.667+09:00	START RequestId: b0a4fea6-e5dd-4fcc-9538-d576e1fcafd4 Version: $LATEST
2023-08-05T13:27:26.668+09:00	[INFO] 2023-08-05T04:27:26.667Z b0a4fea6-e5dd-4fcc-9538-d576e1fcafd4 {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
2023-08-05T13:27:26.670+09:00	END RequestId: b0a4fea6-e5dd-4fcc-9538-d576e1fcafd4
2023-08-05T13:27:26.670+09:00	REPORT RequestId: b0a4fea6-e5dd-4fcc-9538-d576e1fcafd4 Duration: 2.08 ms Billed Duration: 3 ms Memory Size: 128 MB Max Memory Used: 36 MB Init Duration: 118.60 ms

4. AWS Lambda ハンズオン② 他のサービスを呼び出してみる

Translateを呼び出す、Lambda関数を実装します。

1. Translateを呼び出せるようにLambda関数「translate-function」を実装する。
2. LambdaにアタッチされているIAMロールにポリシー「TranslateFullAccess」を追加する。
3. 正しく動作するか確認するため、テストを実行する。

以下のように実装しました。

lambda_function.py
import json
import boto3

translate = boto3.client('translate')

def lambda_handler(event, context):
    
    input_text = 'おはよう'
    
    response = translate.translate_text(
        Text=input_text,
        SourceLanguageCode='ja',
        TargetLanguageCode='en',
    )
    
    output_text = response.get('TranslatedText')
    
    return {
        'statusCode': 200,
        'body': json.dumps({
            'output_text': output_text
        })
    }

続いて、Lambda関数がTranslateにアクセスできるようIAMロールにポリシーを追加していきます。

Lambda関数の「設定」から「ロール名」を選択します。
許可を追加 _ IAM _ Global - Google Chrome 2023_08_05 16_29_52.png

「許可を追加」から「ポリシーをアタッチ」を選択します。
translate-function-role-wg9ienoq _ IAM _ Global - Google Chrome 2023_08_05 16_16_31.png

検索バーで「Translate」と検索します。
「TranslateFullAccess」を選択して「許可を追加」をクリックします。
AWS Hands-on for Beginners Serverless #1 サーバーレスアーキテクチャで翻訳 Web API を構築する _ AWS Webinar - Google Chrome 2023_08_05 16_20_10.png

無事、ロールにポリシーをアタッチできました。
許可を追加 _ IAM _ Global - Google Chrome 2023_08_05 16_34_03.png

6. Amazon API Gateway ハンズオン① API Gateway を単体で使ってみる

このセクションではまだLambda関数との連携は行いません。
Mockデータを返すAPIを作成します。

  1. 「translate-api」として、APIを作成する。
  2. 「sample」として、リソースを作成する。
  3. 統合タイプを「Mock」としてGETメソッドを作成する。
  4. GETメソッドのテストを行う。
  5. 新しく作成したステージ「dev」にAPIのデプロイを行う。
  6. デプロイしたAPIをURLで呼び出す。

統合レスポンスのマッピングテンプレート「application/json」を作成します。

application/json
{
    "StatusCode": 200,
    "body": {
        {
            "report_id": 5,
            "report_title": "Hello, World"
            
        },
        {
            "report_id": 7,
            "report_title": "こんにちは"  
        }
    }
}

テストを実行すると、無事にレスポンスが返ってきました。
i2ho5luaf3.execute-api.us-east-1.amazonaws.com_dev_sample - Google Chrome 2023_08_05 21_12_26.png

ブラウザでのURL呼び出しも無事にできました。
キャプチャ 2023_08_05 21_05_19.png

7. Amazon API Gateway ハンズオン② API Gateway と Lambda を組み合わせる

API GatewayとLambdaを連携して、入力した日本語を英語に翻訳するAPIを作成します。

  1. すでに作成済みのAPI「translate-api」で「translate」リソースを作成する。
  2. 統合タイプを「Lambda関数」とし、作成済みのLambda関数「translate-function」を選択してGETメソッドを作成する。
  3. GETメソッドのメソッドリクエストで、URL クエリ文字列パラメータ「input_text」を追加する。
  4. APIGatewayのルールに従ってレスポンスを返すようにLambda関数「translate-function」を修正する。
  5. イベントテンプレート「Amazon API Gateway AWS Proxy」を修正し、イベント「APICall」を作成する。
  6. クエリパラメータの文字列を受け取れるように「translate-function」を修正する。
    7.GETメソッドのURLの呼び出しでクエリパラメータを「こんばんは」としてAPIを叩いてみる。

以下のように実装しました。

lambda_function.py
import json
import boto3

translate = boto3.client('translate')

def lambda_handler(event, context):
    
    input_text = event['queryStringParameters']['input_text']
    
    response = translate.translate_text(
        Text=input_text,
        SourceLanguageCode='ja',
        TargetLanguageCode='en',
    )
    
    output_text = response.get('TranslatedText')
    
    return {
        'statusCode': 200,
        'body': json.dumps({
            'output_text': output_text
        }),
        'isBase64Encoded': False,
        'headers': {}
    }

クエリパラメータ(input_text)として「こんにちは」を渡すテスト「APICall」を実行します。

翻訳結果として「Hi」が無事に返ってきました。
また、今回レスポンスとして追加した「isBase64Encoded」と「headers」も無事に確認できました。

Response
{
  "statusCode": 200,
  "body": "{\"output_text\": \"Hi\"}",
  "isBase64Encoded": false,
  "headers": {}
}

ブラウザでのURL呼び出しを行います。クエリパラメータとして「こんばんは」をURLに入力します。
無事にレスポンスが返ってきました。※GETメソッドを作成するとき、「Lambdaプロキシ統合の使用」にチェックしていないとここで、エラーが発生します。

{"output_text": "Good evening"}

9. Amazon DynamoDB ハンズオン①テーブルを作ってみる

DynamoDBのテーブルを作っていきます。

  1. 「translate-history」テーブルを作成する。
  2. 手動で項目を作成する。

「timestamp」をパーティションキーとした「translate-history」テーブルを作成しました。
また、項目を作成しました。
項目 _ Amazon DynamoDB Management Console - Google Chrome 2023_08_06 1_25_12.png

10. Amaozn DynamoDB ハンズオン② API Gateway と Lambda と DynamoDB を組み合わせる

翻訳履歴をDynamoDBにPUTするよう、Lambda関数を実装していきます。

  1. 翻訳APIを叩くたびに、「timestamp」、「input_text」、「output_text」をDynamoDBにPUTするようLambda関数を修正する。
  2. Lambda関数にアタッチされているIAMロールにポリシー「AmazonDynamoDBFullAccess」をアタッチする。
  3. 作成済みのテスト「APICall」を実行し、実際にDynamoDBにPUTできているか確認する。
  4. GETメソッドのURLの呼び出しでURLにアクセスし、APIを叩いてDynamoDBにPUTできているか確認する。

以下のように実装しました。

lambda_function.py
import json
import boto3
import datetime

translate = boto3.client('translate')

dynamodb_translate_history_tbl = boto3.resource('dynamodb').Table('translate-history')


def lambda_handler(event, context):
    
    input_text = event['queryStringParameters']['input_text']

    response = translate.translate_text(
        Text=input_text,
        SourceLanguageCode="ja",
        TargetLanguageCode="en"
    )

    output_text = response.get('TranslatedText')
    
    dynamodb_translate_history_tbl.put_item(
        Item = {
            'timestamp': datetime.datetime.now().strftime("%Y%m%d%H%M%S"),
            'input_text': input_text,
            'output_text': output_text
            
        }
    )
    
    return {
        'statusCode': 200,
        'body': json.dumps({
            'output_text': output_text
        }),
        'isBase64Encoded': False,
        'headers': {}
    }

クエリパラメータ(input_text)として「こんにちは」を渡すテスト「APICall」を実行します。

無事に「translate-history」テーブルにputされています。
項目 _ Amazon DynamoDB Management Console - Google Chrome 2023_08_06 1_49_34.png

続いて、ブラウザでのURL呼び出しを行います。クエリパラメータとして「ハンズオン完走しました」をURLに入力します。
無事に、レスポンスが返ってきました。

項目 _ Amazon DynamoDB Management Console - Google Chrome 2023_08_06 2_01_21.png

こちらも、無事に「translate-history」テーブルにputされています。
項目 _ Amazon DynamoDB Management Console - Google Chrome 2023_08_06 2_02_42.png

落ち穂拾い

  • AWS Lambdaで、コンテナが再利用されるとグローバルスコープ(ハンドラ外)に記述されている部分はウォームスタートになり、ローカルスコープ(ハンドラ内)に記述されている部分は再利用されない。
  • 今後どのようにサーバーレスを学んでいくかのラーニングパスの紹介

まとめ

無事にハンズオン完走することができました。
ハンズオンでの学習はアウトプットとして、とてもためになると感じたので、気になるサービス・学びたいサービスがあれば積極的に触ってみて学習していきたいと思います。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0