質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
AWS Lambda

AWS Lambdaは、クラウド上でアプリを実行できるコンピューティングサービス。サーバーのプロビジョニングや管理を要せず複数のイベントに対してコードを実行します。カスタムロジック用いた他AWSサービスの拡張やAWSの規模やパフォーマンスを用いたバックエンドサービスを作成できます。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

2回答

1374閲覧

関数を非同期に処理する方法

yuki_90453

総合スコア326

AWS Lambda

AWS Lambdaは、クラウド上でアプリを実行できるコンピューティングサービス。サーバーのプロビジョニングや管理を要せず複数のイベントに対してコードを実行します。カスタムロジック用いた他AWSサービスの拡張やAWSの規模やパフォーマンスを用いたバックエンドサービスを作成できます。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

0グッド

1クリップ

投稿2020/07/04 06:35

概要

POSTで受信したデータを元に処理を実行するコードを書いています。送信元からの要件で5秒以内に応答が必要な為、処理に時間がかかるコードを非同期に実行して、先に送信元へ応答を済ませたいと考えています。

コード

export const handler=async(event:any, context:Context, callback:Callback)=>{ const order = JSON.parse(event.body) // 処理に時間のかかるコード await heavyMetod(order) callback(null, { statusCode: 200, headers: {'Access-Control-Allow-Origin':'*'}, body:'Done' }) } // puppeteerを使用するため実行時間が10秒ほど掛かってしまいます。 // この部分を非同期にバックグラウンドで実行したいと考えております。 const heavyMetod = async(data) =>{ const browser = await chromium.puppeteer.launch({ args: chromium.args, defaultViewport: chromium.defaultViewport, executablePath: await chromium.executablePath, headless: chromium.headless, }) let page = await browser.newPage(); await page.goto(data.url); const elem = await page.$x("//input[@name='auth']") if(Array.isArray(elem)){ await Promise.all([ elem[0].click(), page.waitForNavigation() ]) console.log(await page.title()) }else{ await Promise.all([ elem.click(), page.waitForNavigation() ]) console.log(await page.title()) } await browser.close() }

試したこと

処理に時間のかかる関数(heavyMetod)を呼び出す際、await heavyMetod(order)部分をheavyMetod(order)に書き換えて実行してみましたが、同期して呼び出されており全体の実行時間は減りませんでした。

このheavyMetod自体はPromiseを返すのでローカル環境で実行した際は<pending>なります。
しかし、ライブ環境(Lambda)では全体の実行時間が減らない事から同期的に実行されていると思います。

質問

  1. 上記のheavyMetodは非同期に実行出来ない理由についてご指摘頂けないでしょうか?
  2. Lambda上では非同期関数も同期的に実行される事はありえますか?

宜しくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

(普段はPythonでlambdaを書いているので、間違ってたらすみません)

API Gateway の裏の lambda は常に同期実行なので、await を待ってしまっているんじゃないかと思います(ハッキリしたソースは思い出せませんが、そういう記述がどこかにあったような気がします)

似たようなハマり方をした方がいらっしゃるようなのでリンクを提示します。

https://qiita.com/suetake/items/3fc945a380af65ecf82d

https://www.slideshare.net/takehirosuemitsu/awsapi-gatewaylambdas3

このコード単体に収まる話ではなくなりますが、重たい非同期処理をやりたいのであればアーキテクチャの設計で対処するのが良いと思います。上記の Qiita の記事は直接別のlambdaを呼び出していますが、アーキテクチャとしてはあまり美味しくないように思います。SNS, SQS あたりを挟んで、それを別の lambda がサブスクライブし、そこで heavyMethod を実装するのがご質問の要件に対する回答としては綺麗かなと思います。

投稿2020/07/04 12:30

hassaku_63

総合スコア92

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

応答が早くなる事は不可能です。
基本的にWebサーバは全ての処理を実行してから結果を投げ返すものなので。

じゃあどうすんねんという事で、
設計を一緒に考えていきましょう。


ファミレスに例えましょう。

ファミレスは立ち食い蕎麦屋さんではないので、
ホカホカの麺がスタンバっていて料理を5秒以内に提供出来るわけではありません。
なので、席に一度通して、お冷を渡して待ってもらいますよね。

重い処理は革命が起きない限り早くは終わりません。
なのでファミレスと同じようなやり方をします。

ではWebサーバに応用していきましょう。


Webサーバはエンドポイントを2つ用意します。

  • 重い処理を受け付けて、DBにオーダーを保存してすぐ結果を返す
  • 結果を確認する

AWS Lambdaを利用しているのであれば、
DBへオーダーの保存をするのではなくSQSメッセージを作ってタスクにし、
別の重い処理を逐次実行するLambda関数なり、EC2上のプログラムで実行させてタスクをこなせば良いです。

すぐ結果を返すサーバは一意のオーダーIDを返します。

また結果を確認するサーバは、
オーダーIDを受け取り、その結果が揃っているかを確認します。
結果が揃ってなければもう一回接続しなおしてねの設計なら良いと思います。


そもそもの話をしても良いですか?
5秒以内ってのはどういう意味でしょうか?

これは画面上に砂時計が出て固まる時間を指しているんじゃないかと思います。
Ajax通信が100秒待たせようが別に問題ないじゃないですか。
Ajax通信は元々非同期なので、アニメーションやDOMを変更しながらファミレスのお冷出しみたいな事すれば良いんですよ。

これって別の重要な話がありませんか?
「重い処理だから二重実行にならないようにしろ」だとか、
Lambdaの制限時間的な話があったり、
キャッシュ取って何度も実行させるなみたいな話じゃないんですか?

前提条件が足りないので、
質問開始時点でどう実現してもUX上のメリットは低く、やる意味あるの?と思います。

これに関しては出せる前提条件が機密情報だったりしますので、
上司や先輩(クライアント?)ともう少し話し合ってみてください。

投稿2020/07/06 04:57

miyabi-sun

総合スコア21203

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問