GCS Notification 功能實作 (二):應用於 Google App Engine
Object Change Notification 是如何運作的?
application 端可以透過監控請求,去監控 GCS的 object 是否有變動。監控請求初始會建立一個 Notification Tunnel,當 GCS有變動時(新增、更新、刪除檔案),GCS 會透過 Notification Tunnel 傳送通知給 application端。目前 Notification Tunnel 只有一種類型,Web Hook。任何可以接收 HTTP POST 請求的伺服器都可以使用此方法。
參數簡介
• ApplicationUrl:應用程式的 URL,必須為 HTTPS URL,不支援 HTTP
• ChannelId:每個通知頻道的 ID,會協同通知訊息傳送給應用程式
• BucketName:被監聽的資源 ID,停止通知時需要此 ID
• ClientToken:(optional) 讓用戶端認證的 token
• 監聽 bucket
$ gsutil notification watchbucket [-i ChannelId] [-t ClientToken] ApplicationUrl gs://BucketName
• 移除通知設定
$ gsutil notification stopchannel ChannelId ResourceId
如何開放權限給 change notification
1. 新增一個 Service Account
• API & Services的子項目 Credentials
• 點選 Create credentials 並選擇 Service account key
• 下拉式選單 Service account 請選擇 New service account
• 輸入必填的 Service account name, ID 可自行修改
• Key type 選擇 JSON
• 創立後會下載 JSON 格式的 Key
2. 賦予 gsutil 權限使用 Service Account
3. 更新 Cloud SDK
$ gcloud components update
4. 驗證 Service Account Email (開啟GCP Console中 IAM & admin 的 Service accounts ,並複製剛剛新增的 Service Account) 以及 key
$ gcloud auth activate-service-account [Service-Account信箱] --key-file [路徑/key的名稱]
// 驗證成功會出現以下訊息
$ Activated service account credentials for: [Service-Account信箱]
5. 再次確認是否驗證成功,會看到信箱前面有 active 的星號
$ gcloud auth list
Credentialed Accounts
ACTIVE ACCOUNT
* [Service-Account信箱]
6. 指定接收通知的 Domain
• 確認您是這個 Domain 的管理者
• 點選 Add domain
• 輸入指定的 Domain 並新增
7. 移除通知設定
$ gsutil notification stopchannel ChannelId ResourceId
應用程式範例
接下來會帶您建立一個 App Engine 的應用程式執行 Object Notification
1. 創立一個 Bucket,[Bucket Name] 為自填參數
$ gsutil mb gs://[Bucket Name]/
Creating gs://[Bucket Name]... //表示成功新增Bucket
2. 新增一個 For App Engine 的資料夾,裡面包括 app.yaml 和 change_notification_client.py 兩個檔案
(app.yaml 程式碼)
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
script: change_notification_client.app
(change_notification_client.py 程式碼)
import json
import logging
import webapp2
class MainPage(webapp2.RequestHandler):
""Process notification events.""
def get(self):
logging.info("Get request to notification page.")
self.response.write("Welcome to the notification app.")
def post(self): # pylint: disable-msg=C6409
""Process the notification event.
notification message in the log.
""
logging.debug(
'%snn%s',
'n'.join(['%s: %s' % x for x in self.request.headers.iteritems()]),
self.request.body)
# The following code is for demonstration. Replace
# it with your own notification processing code.
if 'X-Goog-Resource-State' in self.request.headers:
resource_state = self.request.headers['X-Goog-Resource-State']
if resource_state == 'sync':
logging.info('Sync message received.')
else:
an_object = json.loads(self.request.body)
bucket = an_object['bucket']
object_name = an_object['name']
logging.info('%s/%s %s', bucket, object_name, resource_state)
else:
logging.info("Other post.")
logging.getLogger().setLevel(logging.DEBUG)
app = webapp2.WSGIApplication([('/', MainPage)], debug=True)
3. 部署這個 app 並且確認是否部署成功
$ gcloud app deploy //部署
$ gcloud app browse //部署的應用程式會在 http://[YOUR_PROJECT_ID].appspot.com
// [YOUR_PROJECT_ID]為使用者的project id
4. 給予應用程式 Bucket 的權限
$ gsutil acl ch -u [YOUR_PROJECT_ID]@appspot.gserviceaccount.com:OWNER gs://[Bucket Name]
5. 到 APIs & Services 的 Credentials 點選 Create Credentials 然後選擇 Service Account Key
6. 之後選擇過剛剛賦予權限的 Service Account (這邊是選擇 App Engine Default Service Account)
7. 格式選擇 JSON,創立後會下載 JSON 格式的 Key
8. 賦予 gsutil 權限使用 Service Account
$ gcloud auth activate-service-account [Service-Account信箱] --key-file [路徑/key的名稱]
// 驗證成功會出現以下訊息
$ Activated service account credentials for: [Service-Account信箱]
9. 監控 Bucket
$ gsutil notification watchbucket [ApplicationURL] gs://[Bucket Name]
//[ApplicationURL] = https://[YOUR_PROJECT_ID].appspot.com/
10 .測試
$ curl -X Post https://[YOUR_PROJECT_ID].appspot.com
$ gsutil cp [OBJECT] gs://[Bucket Name]/
// [OBJECT] 為任意一個檔案
11. 開啟 console 的 Stackdriver Logging 的 Logs 查看 Log