この記事はPTAのアドベントカレンダー24日目の記事です。
概要
- EventBridgeのAPI Destinationという機能を使うと、外部API呼び出しを非同期的に実行できる。
- APIのレートリミット内に収まるように自動的に調整してくれる。
- SlackのAPIで実験してみました。
EventBridge API Destinationとは
EventBridge API Destinationは、EventBridgeのターゲットにHTTP APIの呼び出しを指定できる機能です。
以下の特徴があります。
- 自動リトライ
- DLQにも対応
- 3種類の認証方式に対応
- APIのレートリミット内に収まるように自動的に調整
実装
全体像
実装・設定するものは以下です。
- SlackのWebhook URLを取得
- EventBridgeのAPI Destination・接続を作成
- EventBridgeのイベントバスを作成
- EventBridgeのルールを作成
- EventBridgeのイベントを発行するコードを実装
SlackのWebhook URLを取得
こちらを参考にSlackのWebhook URLを取得します。
EventBridgeのAPI Destination・接続を作成
1. 接続を作成


※今回はWebhook URLを使用するので認証は不要なのですが、必須なので適当に設定しました。ただ、本当はSlackアプリを作成してOAuth Tokenを取得し、認証を設定した方が良い気がします。
2. API Destinationを作成
API Destination(API 送信先)を作成します。
-
API 送信先エンドポイント
の欄にWebhook URLを貼り付けてください。 - SlackのIncoming webhooks APIのレートリミットは1秒に1リクエストまでなので、
1秒あたりの呼び出しレート制限
の欄に1と入力します。

EventBridgeのイベントバスを作成
EventBridgeのルールを作成
-
ターゲットタイプ
にEventBridge APIの宛先
を指定し、先程作成したAPI送信先を指定してください。
-
ターゲット入力を設定
で一致したイベントの一部
を選択肢、$.detail
と入力します。
EventBridgeのイベントを発行するコード
今回はGolangで実装しました。
package main
import (
"encoding/json"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/eventbridge"
)
type Payload struct {
Text string `json:"text"`
}
func main() {
payload := Payload{Text: "test-after"}
p, err := json.Marshal(payload)
if err != nil {
panic(err)
}
sess, err := session.NewSession(&aws.Config{Region: aws.String("us-east-1")})
if err != nil {
panic(err)
}
e := eventbridge.New(sess)
for i := 0; i < 200; i++ {
_, err := e.PutEvents(&eventbridge.PutEventsInput{
Entries: []*eventbridge.PutEventsRequestEntry{{
EventBusName: aws.String("test"),
Source: aws.String("test.slack.post"),
DetailType: aws.String("detail"),
Detail: aws.String(string(p)),
}},
})
if err != nil {
panic(err)
}
}
}
実験
Before(SlackのWebhook URLを直接呼び出す)
比較のため、EventBridge API Destinationを経由せずSlackのWebhook URLに直接リクエストを大量に送ってみます。
package main
import (
"encoding/json"
"net/http"
"net/url"
)
var hookURL = "" // NOTE: 今回は実験のためWebhook URLを変数に定義しましたが、危険なのでSecrets Managerなどに保管してください。
type Payload struct {
Text string `json:"text"`
}
func main() {
payload := Payload{Text: "test"}
p, err := json.Marshal(payload)
if err != nil {
panic(err)
}
for i := 0; i < 200; i++ {
resp, err := http.PostForm(hookURL, url.Values{"payload": {string(p)}})
if err != nil {
panic(err)
}
if resp.StatusCode != http.StatusOK {
panic(resp.StatusCode)
}
err = resp.Body.Close()
if err != nil {
panic(err)
}
}
}
結果
レートリミットを超えるリクエストを大量に送信すると、以下のように警告文が表示された後しばらくして、429(Too Many Requests)レスポンスが返ってきます。1

panic: 429
After(EventBridge API Destinationを使って呼び出す)
結果
まとめ
- EventBridge API Destinationを使用することで、レートリミットを気にせずにAPIを呼び出せるようになりました。
- 厳しいレートリミットを設けているAPIを利用する際などに活躍しそうです。
- 一方で、ログが出力されない(自分が見つけられていないだけかも)ので、デバッグなどは難しくなる印象を受けました。
参考
- https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-api-destinations.html
- https://slack.com/intl/ja-jp/help/articles/115005265063-Slack-%E3%81%A7%E3%81%AE-Incoming-Webhook-%E3%81%AE%E5%88%A9%E7%94%A8
- https://api.slack.com/docs/rate-limits
-
SlackのIncoming webhooks APIではレートリミットを超えた場合に短期間バーストします。その際にこのメッセージが表示されるようです。 ↩