###### tags: `卒業制作` # バックエンド開発 > 「たびたび」のバックエンド側の情報共有用 > AWSのLambdaでPythonを書く!!自由に追記してね!! ## 記事とかの共有 [AWS SAMとRDSの接続](https://chariosan.com/2020/01/12/sam_rds_python/) [AWS SAMのドキュメント](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/what-is-sam.html) [Python+mysql-connector-python の使い方まとめ(Qiita)](https://qiita.com/valzer0/items/2f27ba98397fa7ff0d74) [Python命名規則一覧(Qiita)](https://qiita.com/naomi7325/items/4eb1d2a40277361e898b) ## 不明点や調べることなどのメモ場所 * lambda マッピングテンプレート ## 使うツールとか技術 * Docker(ローカルでAPI Gatewayを起動するため) * Python 3.8 * Git * MySQL 5.* * AWS SAM(ローカル開発とデプロイ) * AWS API Gateway(リクエスト) * AWS Lambda(プログラム) * AWS S3(ストレージ) * アルバムの画像保存 * AWS Cognito(認証) * 独自認証(Email&PassWord) * ソーシャルログイン(Google) * Cognitoでユーザー登録時にトリガーでLambda実行してRDSのテーブルにユーザー情報を保存する ## Lambdaのローカル開発 ### Git 運用メモ * developブランチから新しくブランチを切る * developにpushする * developにmergeする * apiキーとか公開してはダメなものに気を付ける ### ディレクトリ構成とURL設計 * SAMのディレクトリとAPIのURLを書く ### AWS SAMでのローカル開発環境構築 * 環境構築と使い方 [AWS SAM CLI 再入門](https://qiita.com/hayao_k/items/7827c3778a23c514e196)を見ると環境構築とコマンドについてある程度わかる * gitとdockerが必要 Windowsは上記のQiita記事見ればできるはず ``` Mac版のbrewを使ったインストール $ brew tap aws/tap $ brew install aws-sam-cli $ sam --version //バーション出ればOK ``` #### 実行方法 ``` $ sam build // 全部ビルド(全部するので時間かかる) $ sam build [Lambda関数名] // 単一ビルド $ sam local invoke [Lambda関数名] // コマンド実行 $ sam local start-api // API GateWay 起動 ``` ### CloudFormationを書く(template.yaml) * ローカルでAPI Gatewayを立てた時実行される * これをもとにAWS本番環境にデプロイする * 1つの関数で下のyamlを書くのでめっちゃ多くなる・・・どうしたもんか。 ``` Resources: TestFunction: #Lambda関数名 Type: AWS::Serverless::Function #Lambda使う宣言 Properties: CodeUri: test_function/ #関数フォルダのパス Handler: app.lambda_handler #実行する関数(ファイル名.関数名) Runtime: python3.8 #ランタイム(言語) Events: HelloWorld: Type: Api Properties: Path: /test #localhost:3000/test Method: get #get,post ``` ## LambdaとPythonのサンプル [サンプルプログラム](https://github.com/matsukawa-s/lambda_sample) * Lambda関数使うのに2つの引数は必要(event,context) * eventの中身はいろいろ書いてる * eventの中にget送信のパラメータやpost送信のデータが入ってる ### GETリクエスト処理 例:127.0.0.1:3000/getread/{id} ``` def lambda_handler(event, context): # eventのpathParametersに入ってくる id = event["pathParameters"]["id"] return { "statusCode": 200, "body": json.dumps({ "message": "hello world", }), } ``` ### POSTリクエスト処理 * データはjsonで送る * HTTPヘッダーCORSをつけて送信する * (よくわからないのでまた調べるけど、付けないとエラーでる) ``` Access-Control-Allow-Origin : * ``` 例:127.0.0.1:3000/create ``` def lambda_handler(event, context): # eventのbodyに入ってくる # jsonパース data = json.loads(event["body"]) id = data["id"] name = data["name"] job = data["job"] return { "statusCode": 200, "body": json.dumps({ "message": "hello world", }), } ``` ### RDS(MySQL)と繋ぐ * mysql.connectorを使用する(他にもmysql用のライブラリはある) mysql接続(connの接続部分はあとでLayer化して共通処理にする) ``` conn = mydb.connect( # dockerからホストのmysqlに繋いでる # 環境に合わせて変える # host='host.docker.internal', host=[ホスト] port=[ポート番号:3306], user=[ユーザー名], password=[パスワード], database=[データベース名:tabitabi_db] ) # カーソル作成 # dictionary=Trueでカラム名をキーに辞書型で返ってくる cur = conn.cursor(dictionary=True) cur.execute("SELECT * FROM emp"); rows = cur.fetchall() # カーソルとコネクションを閉じる cur.close() conn.close() ``` * returnでjson.dumpで射影の結果を入れて返すといい感じに返ってくる ``` return { "statusCode": 200, "body": json.dumps(rows), } ``` ### ライブラリと共通処理(Layer) > ライブラリやmysqlの接続とか共通で使うものをまとめる為のもの * レイヤー作成 ``` $ mkdir [layer名] $ touch layer名/requirements.txt ``` requirements.txt(ここにライブラリ名書く) ``` numpy mysql-connector-python # mysqlコネクターライブラリ ``` ### デプロイ * template.yamlを元にデプロイする