2014-07-20 22 views
0

我有一個存儲在GCS上並由GCS客戶端庫創建和更新的文本文件(比如「X」)。我使用GAE Python。在我的網站的用戶添加一些數據時,我會向「默認」隊列添加一個Task(taskqueue.Task),以執行一些操作,包括修改文件(「X」)。如何鎖定Google Cloud Storage文本文件以執行類似操作

有時候,我獲取日誌中的以下錯誤:

E 2014-07-20 03:19:06.238 500 3KB 430ms /t 
0.1.0.2 - - [19/Jul/2014:14:49:06 -0700] "POST /t HTTP/1.1" 500 2569 "http://www.myappdomain.com/p" "AppEngine-Google; (+http://code.google.com/appengine)" "www.myappdomain.com" ms=430 cpu_ms=498 cpm_usd=0.000287 queue_name=default task_name=14629523467445182169 instance=00c61b117c48b4db44a58e0d454310843e7848 app_engine_release=1.9.7 trace_id=3db3eb580b76133e90947539c0446910 
    I 03:19:05.813 [class TaskQueueWorker] work=[sitemap_index_entry] 
    I 03:19:05.813 country_id=[US] country_name=[USA] state_id=[CA] state_name=[California] city_id=[SVL] city_name=[Sunnyvale] 
    I 03:19:05.836 locality_id_old=[-1] locality_id_new=[28] 
    I 03:19:05.879 locality_name_old=[] locality_name_new=[XYZ] 
    I 03:19:05.879 command=[ADD] 
    E 03:19:06.207 File on GCS has changed while reading. 
Traceback (most recent call last): 
    File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1535, in __call__ 
    rv = self.handle_exception(request, response, e) 
    File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1529, in __call__ 
    rv = self.router.dispatch(request, response) 
    File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher 
    return route.handler_adapter(request, response) 
    File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1102, in __call__ 
    return handler.dispatch() 
    File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 572, in dispatch 
    return self.handle_exception(e, self.app.debug) 
    File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 570, in dispatch 
    return method(*args, **kwargs) 
    File "/base/data/home/apps/s~myappdomain/1.377368272328585247/main_v3.py", line 15259, in post 
    gcs_file = gcs.open (index_filename, mode='r') 
    File "/base/data/home/apps/s~myappdomain/1.377368272328585247/cloudstorage/cloudstorage_api.py", line 94, in open 
    buffer_size=read_buffer_size) 
    File "/base/data/home/apps/s~myappdomain/1.377368272328585247/cloudstorage/storage_api.py", line 220, in __init__ 
    check_response_closure() 
    File "/base/data/home/apps/s~myappdomain/1.377368272328585247/cloudstorage/storage_api.py", line 448, in _checker 
    self._check_etag(resp_headers.get('etag')) 
    File "/base/data/home/apps/s~myappdomain/1.377368272328585247/cloudstorage/storage_api.py", line 476, in _check_etag 
    raise ValueError('File on GCS has changed while reading.') 
ValueError: File on GCS has changed while reading. 
    I 03:19:06.235 Saved; key: __appstats__:045800, part: 144 bytes, full: 74513 bytes, overhead: 0.002 + 0.004; link: http://www.myappdomain.com/_ah/stats/details?time=1405806545812 

我懷疑是多個觸發任務嘗試在同一時間打開和更新文件(「X」)。這導致了上述例外。請建議一種方法來鎖定對該文件的訪問權限,以便一次只能修改一個任務(類似於事務)。

感謝您的幫助和指導。

UPDATE
另一種方法來防止上述問題可能是修改該隊列的以下參數queue.yaml中之一:

bucket_size

OR

max_concurrent_requests

但是,不確定要修改哪一個。

+1

創建一個任務隊列一次只能執行1個任務,並從該隊列執行所有這些任務呢? –

+0

@PaulCollingwood +1並感謝您的回覆。巧合的是,我也只是想過類似的問題,並且已經更新了這個問題(與您的評論到達同時)。我懷疑要更改哪個參數。我更新了我的問題。能否請你幫忙? – gsinha

+1

我會從max_concurrent_requests = 1開始 –

回答

2

max_concurrent_requests = 1的任務隊列應確保一次只對文件進行一次編輯。

https://developers.google.com/appengine/docs/python/config/queue#Python_Defining_push_queues_and_processing_rates

如果要防止過多的任務,從一次或 運行避免數據存儲區爭,你用max_concurrent_requests。

max_concurrent_requests(推送隊列中只) 設置可以在任何給定時間 在指定的隊列中執行的任務的最大數量。該值是一個整數。默認情況下,此 指令未設置,並且對最大併發任務數沒有限制。此指令的一個用途是防止太多的 任務同時運行或阻止數據存儲爭用。

限制併發任務的最大數量可以讓您更多地控制隊列的執行速度。例如,您可以限制正在運行隊列任務的實例的數量。 通過限制給定隊列中的併發請求數量,您可以使資源可用於其他隊列或聯機處理。

當然,你應該建立邏輯,讓失敗的任務重新嘗試等等,否則你現在可能會遇到更糟糕的問題。

+0

設置它解決了異常問題。但是,我仍然不確定設置「rate」和「max_concurrent_requests」有什麼區別。 謝謝:) – gsinha

+0

'Rate'更像是您可以在一定的時間內完成多少個工作。所以就像'5/s'一樣(我認爲更準確地說,許多任務可以從一個桶中租出)。如果你有一個快速的任務(以及一個足夠大的'bucket-size'),那麼低速率一次可以有多個請求。 'max_concurrent_requests'強制執行確切的時間可以運行多少個任務。他們一起工作,但是'max_concurrent_requests'更直接地控制你的隊列。 – user3058197

+0

將'Rate'看作每個時間段可以啓動多少個任務(例如,5/s =每秒啓動5個新任務)。 'max_concurrent_requests'是可以同時運行多少個這樣的任務。如果滿足'max_concurrent_requests',任務隊列將不會啓動任務。例如,這對於限制對API的同時調用的數量很有用。 – Jabberwockey

相關問題