8

Đây là một ngoại lệ phổ biến mà tôi nhận được trên nhật ký của ứng dụng hàng ngày, thường là 5/6 lần mỗi ngày với lưu lượng truy cập là 1 nghìn lượt truy cập/ngày :Thời gian chờ của Google App Engine: Hoạt động kho dữ liệu hết hạn hoặc dữ liệu tạm thời không khả dụng

db error trying to store stats 
Traceback (most recent call last): 
    File "/base/data/home/apps/stackprinter/1b.347728306076327132/app/utility/worker.py", line 36, in deferred_store_print_statistics 
    dbcounter.increment() 
    File "/base/data/home/apps/stackprinter/1b.347728306076327132/app/db/counter.py", line 28, in increment 
    db.run_in_transaction(txn) 
    File "/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py", line 1981, in RunInTransaction 
    DEFAULT_TRANSACTION_RETRIES, function, *args, **kwargs) 
    File "/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py", line 2067, in RunInTransactionCustomRetries 
    ok, result = _DoOneTry(new_connection, function, args, kwargs) 
    File "/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py", line 2105, in _DoOneTry 
    if new_connection.commit(): 
    File "/base/python_runtime/python_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 1585, in commit 
    return rpc.get_result() 
    File "/base/python_runtime/python_lib/versions/1/google/appengine/api/apiproxy_stub_map.py", line 530, in get_result 
    return self.__get_result_hook(self) 
    File "/base/python_runtime/python_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 1613, in __commit_hook 
    raise _ToDatastoreError(err) 
Timeout: The datastore operation timed out, or the data was temporarily unavailable. 

chức năng được nâng cao ngoại lệ trên là sau một:

def store_printed_question(question_id, service, title): 
    def _store_TX(): 
     entity = Question.get_by_key_name(key_names = '%s_%s' % \ 
             (question_id, service)) 
     if entity: 
      entity.counter = entity.counter + 1     
      entity.put() 
     else: 
      Question(key_name = '%s_%s' % (question_id, service),\ 
          question_id ,\ 
          service,\ 
          title,\ 
          counter = 1).put() 
    db.run_in_transaction(_store_TX) 

về cơ bản, kiểm tra store_printed_question chức năng nếu một câu hỏi được đưa ra trước đó đã được in, incrementing trong trường hợp đó truy cập có liên quan trong một giao dịch duy nhất.
Chức năng này được thêm bởi một WebHandler cho một công nhân deferred bằng cách sử dụng hàng đợi được xác định trước default mà bạn có thể biết, có tỷ lệ thông lượng là năm lần truy vấn nhiệm vụ mỗi giây. Trên một thực thể có sáu thuộc tính (hai chỉ mục), tôi nghĩ rằng việc sử dụng transactions được điều chỉnh bởi giới hạn tốc độ nhiệm vụ hoãn lại sẽ cho phép tôi tránh thời gian chờ của kho dữ liệu nhưng nhìn vào nhật ký, lỗi này vẫn hiển thị hàng ngày.

Bộ đếm mà tôi đang lưu trữ không quan trọng lắm, vì vậy tôi không lo lắng về việc hết thời gian chờ này; dù sao tôi cũng tò mò tại sao Google App Engine không thể xử lý công việc này ngay cả với tốc độ thấp như 5 nhiệm vụ mỗi giây và nếu giảm tốc độ có thể là một giải pháp khả thi.
A sharded counter trên mỗi câu hỏi để tránh thời gian chờ sẽ là quá mức cần thiết đối với tôi.

EDIT:
Tôi đã đặt giới hạn tốc độ thành 1 nhiệm vụ mỗi giây trên hàng đợi mặc định; Tôi vẫn nhận được lỗi tương tự.

+0

Tác vụ trì hoãn không phải là "trọng lượng nhẹ hơn" so với các tác vụ thông thường theo bất kỳ nghĩa nào ngoại trừ việc chúng dễ viết hơn. Dưới mui xe, chúng được thực hiện với các trình xử lý thông thường. Trong mọi trường hợp, điều đó sẽ không ảnh hưởng đến chi phí của bản thân giao dịch. –

Trả lời

6

Nói chung, thời gian chờ như thế thường là do write contention. Nếu bạn đã có một giao dịch đi và bạn đang viết một loạt các công cụ cho cùng một nhóm thực thể đồng thời, bạn chạy vào viết các vấn đề tranh chấp (một tác dụng phụ của optimistic concurrency). Trong hầu hết các trường hợp, nếu bạn thực hiện entity group nhỏ hơn, điều đó thường sẽ giảm thiểu vấn đề này.

Trong trường hợp cụ thể của bạn, dựa trên mã ở trên, rất có thể là vì bạn nên sử dụng sharded counter để tránh xếp chồng các lần ghi theo thứ tự.

Khả năng khác ít khả năng hơn (được đề cập ở đây chỉ để hoàn thành) là máy tính bảng mà dữ liệu của bạn đang bật là being moved.

+1

Không có nhóm tổ chức nào được xác định, tôi đang cập nhật một Mô hình duy nhất. Việc tranh chấp viết về nhóm thực thể thường làm tăng một loại ngoại lệ khác. Như tôi đã viết trong câu hỏi của tôi, sử dụng một truy cập sharded có vẻ như một overkill trong trường hợp này. – systempuntoout

+1

@systempuntoout Bạn vẫn có thể nhận được sự tranh luận bằng văn bản về các thực thể riêng lẻ nếu bạn đang làm nhiều hơn khoảng 1QPS sửa đổi đối với chúng. Contention _will_ gây ra một ngoại lệ Timeout. –

+0

@Nick yep, việc tranh chấp viết trên nhóm thực thể gây ra lỗi "Giao dịch va chạm cho nhóm tổ chức có khóa ..". – systempuntoout

7

Truy vấn chỉ có thể hoạt động trong 30 giây. Xem câu trả lời của tôi cho this question đối với một số mã mẫu để ngắt truy vấn bằng cách sử dụng con trỏ.

+0

Thời gian chờ mặc định cho các cuộc gọi api là 5 giây. Bạn có thể thay đổi điều này bằng cách cấu hình bối cảnh như sau: ctx: = appengine.Timeout (appengine.NewContext (req), 30 * time.Second) – nilsmagnus

+0

'appengine.Timeout' now' context.WithTimeout' – murrekatt

Các vấn đề liên quan