SQSのdeduplication Idについてよくわかっていなかったのでメモ
deduplication Idの指定にFIFOキューである必要はあるか?
概要
- deduplication Idの指定というのは、ContentBaseDeduplicationの機能の一部
- ContentBaseDeduplicationは、FIFOキューでなければ有効にならない。
つまりContentBaseDeduplicationでデフォルトはメッセージボディ全体でSHA-256がかかるが、その入力値を指定できるという機能。
MessageDeduplicationId
This parameter applies only to FIFO (first-in-first-out) queues.
If you aren't able to provide a MessageDeduplicationId and you enable ContentBasedDeduplication for your queue, Amazon SQS uses a SHA-256 hash to generate the MessageDeduplicationId using the body of the message (but not the attributes of the message).
https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html
詳細
実際に動かしてみる。
前準備
awscliが必要。少し調べてみたところこれはversion 1のものらしい。現在preview段階でversion 2が作られているらしい。
$ pip install awscli
まぁそのあたりは適当に読み替えてもらうということで。
作成
キューを作成(FIFOである必要がある。ContentBaseDeduplicationもtrue)
$ aws sqs create-queue --queue-name hmm-test-test.fifo --attributes file://attr.json { "Attributes": { "QueueArn": "arn:aws:sqs:ap-northeast-1:875885049010:hmm-test-test.fifo", "ApproximateNumberOfMessages": "0", "ApproximateNumberOfMessagesNotVisible": "0", "ApproximateNumberOfMessagesDelayed": "0", "CreatedTimestamp": "1579249134", "LastModifiedTimestamp": "1579249575", "VisibilityTimeout": "1", "MaximumMessageSize": "262144", "MessageRetentionPeriod": "345600", "DelaySeconds": "0", "ReceiveMessageWaitTimeSeconds": "0", "FifoQueue": "true", "ContentBasedDeduplication": "true" } }
attr.json
{ "ContentBasedDeduplication": "true", "FifoQueue": "true", "VisibilityTimeout": "1" }
エラー
指定をミスってタイポなどしたときにはこういうメッセージ。
An error occurred (InvalidAttributeName) when calling the SetQueueAttributes operation: Unknown Attribute contentBaseDeduplication.
FIFOじゃないキューの場合、これも属性が存在しないというメッセージになる。
aws sqs set-queue-attributes --queue-url $(make -s get-url) --attributes VisibilityTimeout=60,ContentBasedDeduplication=true An error occurred (InvalidAttributeName) when calling the SetQueueAttributes operation: Unknown Attribute ContentBasedDeduplication.
実際の実行
実際に実行してみる。はじめはdeduplication Idを指定しないもの。次は指定したもの。 最後にpurge queueを呼んで上げるとまっさらな状態で試せる。
deduplication Idの指定なし
普通にsendするとbody全体でdeduplicationIDは計算される。つまり2個sendしたら2個receiveできる。
aws sqs send-message --queue-url $(make -s get-url) --message-body file://data.json --message-group-id xxx { "MD5OfMessageBody": "ae0db7789084c03784774df52fef6e9c", "MessageId": "cfc69b42-d98f-409e-b786-50f1c044d192", "SequenceNumber": "18851031995790575616" } aws sqs send-message --queue-url $(make -s get-url) --message-body file://data2.json --message-group-id xxx { "MD5OfMessageBody": "86d5a3290cf61524f71b015752eb0a48", "MessageId": "110713fb-b36e-485b-99c3-1829bb5ff013", "SequenceNumber": "18851031996249583616" } aws sqs receive-message --queue-url $(make -s get-url) --message-attribute-names All --max-number-of-messages 10 { "Messages": [ { "MessageId": "cfc69b42-d98f-409e-b786-50f1c044d192", "ReceiptHandle": "AQEBMmRPGvnTnpFn5Es2+a5N+JhGAsH7OkvoAr3CxBMzF+1Y0LQCtx52HpdY0FINte4Xcn2gj3gq+OWwmv84KdaNuLkXqOOoxeVCtZtBisa10+PlGgEVoT2/C+Qb/emFlt8K9JTGCCr6dGkWgaJ+treb1HRQ3tIOk+cD2xqWOdILWl4c3So0yLHkO9m6PK2i/zt31DZjUBXHgz+bwgpEMpsy19+wPTCASWNEK4AtVPpFlKAYjvoNiW3mBv4bDy7AnleckJaXX9Vs4cPORjSS/5Zs5/o+7LZhRzTOSWVH7Y+Ca14=", "MD5OfBody": "ae0db7789084c03784774df52fef6e9c", "Body": "{\n \"message\": \"hello\",\n \"name\": \"foo\"\n}\n" }, { "MessageId": "110713fb-b36e-485b-99c3-1829bb5ff013", "ReceiptHandle": "AQEBMY/Ji/xn65xpgXNlEHVZuaeIwM2ivjA9oI/AiRJLNkxKaXujICFU9t7+g+YcZDjxZxYPxMHF8qfdyX0igS291NFhFrZLfjolJpSvj/PDx9SrdMBS+7FeM/tgL5/xMpmkC7zQW6JhnOLEjlplWechb769iCO3wyOi20jnww44KWlVS0t/LCX46iIGPiISijqQI4B9ELRWTCBfWeS27TirZ++PxCXmDXy2jkVcskbYZ93l/KZrUsdroGyLjFHzMbTGFUIphIByVzcSB9t5Xzl5tFAQytJmkezsbYIQT6lOCiM=", "MD5OfBody": "86d5a3290cf61524f71b015752eb0a48", "Body": "{\n \"message\": \"byebye\",\n \"name\": \"foo\"\n}\n" } ] } aws sqs purge-queue --queue-url $(make -s get-url)
はい。
この時のファイルは以下
data.json
{ "message": "hello", "name": "foo" }
data2.json
{ "message": "byebye", "name": "foo" }
はい。
deduplication Idの指定あり
deduplication Idを指定した場合にはそれが使われる。したがって2個sendしても1個だけ。
--message-deduplication-id
で指定できる。
aws sqs send-message --queue-url $(make -s get-url) --message-body file://data.json --message-group-id xxx --message-deduplication-id same-id { "MD5OfMessageBody": "ae0db7789084c03784774df52fef6e9c", "MessageId": "28dde929-ea95-4a9b-ba2a-eb834f0d8137", "SequenceNumber": "18851032041886447872" } aws sqs send-message --queue-url $(make -s get-url) --message-body file://data2.json --message-group-id xxx --message-deduplication-id same-id { "MD5OfMessageBody": "86d5a3290cf61524f71b015752eb0a48", "MessageId": "28dde929-ea95-4a9b-ba2a-eb834f0d8137", "SequenceNumber": "18851032041886447872" } aws sqs receive-message --queue-url $(make -s get-url) --message-attribute-names All --max-number-of-messages 10 { "Messages": [ { "MessageId": "28dde929-ea95-4a9b-ba2a-eb834f0d8137", "ReceiptHandle": "AQEBTwnYAaCVQlHPMwMAIz/Yuq5O+xuWyDSscaVzS7EvDHt+k+anTOI2NqpNRmdijvCmEqYHBmGSLvisSo2ouSt6x0Db3Y7I69Fr63VDY38l7KaKl2wIRj8gLKp8z/wSa8a/O8pIxR+eVMxMXyHIRNmxq+QnaQf7io+91wKb0AGhXY+uxMEhYIa+Nsd31Rk/BwARUwdO0b4ndRsF4+YyO1pFM6pTcLOWoEPnFj3rOBASBtchF5EeKyVIYeHuAz0uBmowXzNNwL6cFoKdT1xeMMWOy2HWc7Yn9xV94Id9N4DRBoY=", "MD5OfBody": "ae0db7789084c03784774df52fef6e9c", "Body": "{\n \"message\": \"hello\",\n \"name\": \"foo\"\n}\n" } ] } aws sqs purge-queue --queue-url $(make -s get-url)
Makefile
実験に使ったMakefile。
include ../env.mk .DEFAULT_GOAL := list # WARNING : 実際に作成する (write権限) NAME ?= hmm-test-test.fifo # NOTE: # # ContentBaseDeduplication=trueにするとdeduplicationが有効になる # (これにはFIFOである必要がある) # defaultはbodyをハッシュ関数にかける(SHA-256) # MessageDeduplicationIdを指定するとそれが使われる # # - FIFOキューへのsendにはgroupIdの指定が必要 # 作成 00: $(MAKE) create # 属性の表示 01: $(MAKE) get # deduplication idなしでsend 02: $(MAKE) send $(MAKE) receive $(MAKE) purge # deduplication idありでsend 03: $(MAKE) send2 $(MAKE) receive $(MAKE) purge # clean 04: $(MAKE) clean get: aws sqs get-queue-attributes --queue-url $$(make -s get-url) --attribute-names All create: aws sqs create-queue --queue-name ${NAME} --attributes file://attr.json # 素朴にsend send: aws sqs send-message --queue-url $$(make -s get-url) --message-body file://data.json --message-group-id xxx aws sqs send-message --queue-url $$(make -s get-url) --message-body file://data2.json --message-group-id xxx purge: aws sqs purge-queue --queue-url $$(make -s get-url) # 同じdeduplicationIDを指定してsend send2: aws sqs send-message --queue-url $$(make -s get-url) --message-body file://data.json --message-group-id xxx --message-deduplication-id same-id aws sqs send-message --queue-url $$(make -s get-url) --message-body file://data2.json --message-group-id xxx --message-deduplication-id same-id receive: aws sqs receive-message --queue-url $$(make -s get-url) --message-attribute-names All --max-number-of-messages 10 # usage help: aws sqs help list: aws sqs list-queues get-url: aws sqs get-queue-url --queue-name ${NAME} | jqfpy 'get("QueueUrl")' -r delete: aws sqs delete-queue --queue-url $$(make -s get-url) clean: $(MAKE) purge $(MAKE) delete
aws sqs help
を注意深く読むとわかるけれど。実験も大切。 💫
そしてドキュメントを辿るよりもawscliのヘルプを先に見るのが一番手軽かもしれない。
misc
VisibilityTimeout
VisibilityTimeoutは他のreceiveで取得されない期間のこと
MessageGroupId
並行で処理したい場合にまじめにつけると良い。この単位でgroupingされる。
create, delete
同名のキューを作成したり削除したりを繰り返していたところ、同名のキューの作成は削除後60秒ほど待たないといけないらしい。