Last active
June 30, 2021 03:56
-
-
Save fukasawah/49d77ef6074d7c7eb8e7c241183ad44d to your computer and use it in GitHub Desktop.
AzureのAppServiceでインスタンス間の排他制御をBlobのLeaseを使って試みるサンプル
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
set -ue | |
# | |
# usage) bash lock-and-run.sh "echo" "hello lock world" | |
# | |
### **次の項目は適宜書き換える** ### | |
STORAGE_ENDPOINT=https://{STORAGE_ACCOUNT_NAME}.blob.core.windows.net | |
CONTAINER_NAME=test-container | |
STATUS_FILENAME=my-cron-script.status | |
N=60 | |
### 設定ここまで | |
TOKEN_ENDPOINT=${IDENTITY_ENDPOINT:-http://169.254.169.254/metadata/identity/oauth2/token} | |
if [ "${IDENTITY_HEADER:-}" != "" ]; then | |
# AppService | |
HEADER="X-Identity-Header:${IDENTITY_HEADER}" | |
else | |
# VM | |
HEADER="Metadata:true" | |
fi | |
# IDMSからアクセストークンを得る | |
RET=$(curl --fail -H "$HEADER" --noproxy "*" "${TOKEN_ENDPOINT}?api-version=2019-08-01&resource=https%3A%2F%2Fstorage.azure.com%2F") | |
# PHPでJSONをパースしてアクセストークンを得る | |
ACCESS_TOKEN=$(echo $RET | /usr/local/bin/php -r "echo json_decode(file_get_contents('php://stdin'))->access_token;" 2>/dev/null) | |
# もしくはPython | |
# ACCESS_TOKEN=$(echo $RET | /usr/bin/python3 -c 'import sys,json;print(json.load(sys.stdin)["access_token"])') | |
STATUS_FILE="$STORAGE_ENDPOINT/$CONTAINER_NAME/$STATUS_FILENAME" | |
LOCK_FILE="${STATUS_FILE}.lock" | |
# ロック用のBlobを作る(作成済みの場合はリース中の可能性もあるが、リースを得るためにはまずBlobが存在する必要がある) | |
curl \ | |
-X PUT \ | |
-d "" \ | |
-H "x-ms-blob-type: BlockBlob" \ | |
-H "x-ms-date: $(TZ=UTC date '+%a, %d %b %Y %H:%M:%S GMT')" \ | |
-H "x-ms-version: 2020-08-04" \ | |
-H "Authorization: Bearer $ACCESS_TOKEN" \ | |
"$LOCK_FILE" >/dev/null | |
# Blobのリースを得る | |
GUID=$(cat /proc/sys/kernel/random/uuid) | |
if ! curl --fail \ | |
-X PUT \ | |
-d "" \ | |
-H "x-ms-date: $(TZ=UTC date '+%a, %d %b %Y %H:%M:%S GMT')" \ | |
-H "x-ms-lease-action: acquire" \ | |
-H "x-ms-lease-duration: 15" \ | |
-H "x-ms-proposed-lease-id: $GUID" \ | |
-H "x-ms-version: 2020-08-04" \ | |
-H "Authorization: Bearer $ACCESS_TOKEN" \ | |
"$LOCK_FILE?comp=lease" >/dev/null ; then | |
echo "LOCK FAILED(lease)" >&2 | |
exit $? | |
fi | |
# ロックしたBlobを読み取る(読み取れたら排他制御成功) | |
# 読み取れなかったらexitする | |
if ! curl --fail \ | |
-X GET \ | |
-H "x-ms-lease-id: $GUID" \ | |
-H "x-ms-version: 2020-08-04" \ | |
-H "Authorization: Bearer $ACCESS_TOKEN" \ | |
"$LOCK_FILE" ; then | |
echo "LOCK FAILED(write)" >&2 | |
exit $? | |
fi | |
# ステータスファイルの内容を得る | |
if ! STATUS=$(curl --fail -X GET -H "x-ms-version: 2020-08-04" -H "Authorization: Bearer $ACCESS_TOKEN" "$STATUS_FILE"); then | |
echo "READ FAILED(status_file)" >&2 | |
exit $? | |
fi | |
# ステータスファイルに記録した日時から N 秒以上経過しているか確認 | |
if [[ "${STATUS:-0}" -g "$(date -d "$N sec ago" +%s)" ]]; then | |
# 経過していなかったら早すぎたのでスキップ | |
echo SKIP >&2 | |
exit | |
fi | |
# 最後に実行した日時を記録 | |
if ! curl \ | |
--fail \ | |
-X PUT \ | |
-d "$(date +%s)" \ | |
-H "x-ms-blob-type: BlockBlob" \ | |
-H "x-ms-version: 2020-08-04" \ | |
-H "Authorization: Bearer $ACCESS_TOKEN" \ | |
"$STATUS_FILE" >/dev/null ; then | |
echo "WRITE FAILED(status_file)" >&2 | |
exit $? | |
fi | |
### ここまで到達できれば排他制御ができているはず ### | |
### コマンド実行 | |
exec "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment