AWS Lambda を用いた Amazon SNS のエンドポイント整理
Amazon SNS の Application に紐付いているエンドポイントには Enabled
という Attribute
がついています。文字どおり、有効なエンドポイントかどうかを表すものです。Amazon SNS は賢いので APNS
や GCM
からのフィードバックを受けて、プッシュトークンが無効になった場合に自動的に false にしてくれます。しかし、基本的には Enabled
が false
になったエンドポイントは不要です。したがって、これらを自動的に削除するような仕組みがあったほうがよさそうです。そこで、この記事では AWS Lambda を用いて、それを実現する方法について説明します。
AWS Lambda で動かすスクリプト
コード自体は非常に簡単で以下のような形です。AWS Lambda Function を素早く立ち上げるとしたら本来は python
か node.js
のほうが良いかと思いますが、今回の作りたいものに関してはそれほど即時性を求められるようなものではないと思うので、好きな言語(もちろん Lambda でうごくもの)で問題ないと思います。
import com.amazonaws.auth.{AWSCredentials, BasicAWSCredentials}
import com.amazonaws.regions.{Region, Regions}
import com.amazonaws.services.lambda.runtime.events.SNSEvent
import com.amazonaws.services.lambda.runtime.{Context, RequestHandler}
import com.amazonaws.services.sns.AmazonSNSClient
import com.amazonaws.services.sns.model.{DeleteEndpointRequest, GetEndpointAttributesRequest}
import com.typesafe.config.ConfigFactory
import com.typesafe.scalalogging.slf4j.StrictLogging
import org.json4s._
import org.json4s.native.JsonMethods._
import scala.collection.JavaConversions._
object DeleteEndpointAction extends RequestHandler[SNSEvent, Unit] with StrictLogging {
private type EndpointArn = String
private val conf = ConfigFactory.load()
private val credential: AWSCredentials = new BasicAWSCredentials(conf.getString("amazon_sns.access_key"), conf.getString("amazon_sns.access_secret"))
private val snsClient: AmazonSNSClient = new AmazonSNSClient(credential).withRegion(Region.getRegion(Regions.fromName(conf.getString("amazon_sns.region"))))
override def handleRequest(input: SNSEvent, context: Context) = {
val records = input.getRecords.toList
records.foreach { record =>
val message = record.getSNS.getMessage
if (message != null) {
getEndpointArn(message).foreach { endpointArn =>
logger.info(s"check if enabled: endpoint_arn = $endpointArn")
val enabled = getEnabled(endpointArn).getOrElse(true)
if (!enabled) {
logger.info(s"delete disabled endpoint: endpoint_arn = $endpointArn")
deleteEndpoint(endpointArn)
}
}
} else {
logger.error(s"receive empty message: message_id = ${record.getSNS.getMessageId}")
}
}
}
private def getEndpointArn(message: String): Option[EndpointArn] =
for {
JObject(child) <- parse(message)
JField("EndpointArn", JString(resource)) <- child
} yield resource.headOption
private def getEnabled(endpointArn: EndpointArn): Option[Boolean] = {
val request = new GetEndpointAttributesRequest().withEndpointArn(endpointArn)
try {
val result = snsClient.getEndpointAttributes(request)
result.getAttributes.toMap.get("Enabled").map(_ == "true")
} catch {
case e: Throwable =>
logger.error("failed to get endpoint attributes", e)
None
}
}
private def deleteEndpoint(endpointArn: EndpointArn) = {
val request = new DeleteEndpointRequest().withEndpointArn(endpointArn)
try {
snsClient.deleteEndpoint(request)
} catch {
case e: Throwable => logger.error("failed to delete endpoint", e)
}
}
}
json4s
とか typesafe config
とか scala logging
とか使ってます。よい塩梅に jar
に固めて、 Lambda Function を作って、アップロードしてください。これで AWS Lambda 側の準備は完了です。
Amazon SNS 側の連携設定
Amazon SNS側の作業は次の2点になります。
- 先ほど作った AWS Lambda Function の実行をフックさせるためトピックを作成し、購読(Subscribe)させる
- エンドポイントの整理をしたい対象の Application の持つエンドポイントの状態変化をフックして、トピックに通知を送るように設定する
それぞれについて見ていきましょう。
トピックおよび、サブスクリプションの作成
トピックの作成は通常どおり普通にやってあげれば大丈夫です。とりあえず適当に「endpoint-updated-topic」とでも名前をつけておきましょう。続いて作成したトピックを先ほど作成した Lambda Function に購読させましょう。以下のような形で Protocol で AWS Lambda を選択すれば Endpoint のプルダウンリストに先ほど作成した Lambda Function の ARN がでてくるでしょう。
Application のイベント設定
最後に Amazon SNS の Application に紐づくエンドポイントの Attributes
が変化したイベントをトピックに通知させるように設定します。 Application 一覧の画面で設定対象のアイテムを選択し Actions から configure events を選択してください。
そして、次に表示されるダイアログの Endpoint Updated
の項目に、先ほどつくったトピックの ARN を入力すれば、すべての作業は完了です。
動作確認テスト
設定が終わったら適当に Application へ Endpoint を追加してみて、Edit Endpoint Attributes から Enable を false にしてみてください。きっと自動的にエンドポイントが削除されるはずです。
Application エンドポイントの Attribute 変更以外にも、作成イベント、削除イベントなどをフックすることができるので、やり方次第では様々な連携を AWS Lambda を用いて行うことができると思います。
Author And Source
この問題について(AWS Lambda を用いた Amazon SNS のエンドポイント整理), 我々は、より多くの情報をここで見つけました https://qiita.com/gomi_ningen/items/899750b60b0b15bf57d3著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .