محرك تطبيق Google: كيفية موازاة التنزيلات باستخدام TaskQueue أو Async URLFetch؟
-
30-09-2019 - |
سؤال
يسترجع تطبيق GAE الخاص بي بيانات JSON من موقع طرف ثالث ؛ بالنظر إلى معرف يمثل العنصر للتنزيل ، يتم تنظيم بيانات العنصر على هذا الموقع في صفحات متعددة ، لذا يتعين على الكود الخاص بي تنزيل أجزاء من البيانات ، صفحة تلو الأخرى ، حتى يتم استرداد بيانات آخر صفحة متاحة.
رمزتي المبسطة يبدو هكذا:
class FetchData(webapp.RequestHandler):
def get(self):
...
data_list = []
page = 1
while True:
fetched_data= urlfetch.fetch('http://www.foo.com/getdata?id=xxx&result=JSON&page=%s' % page)
data_chunk = fetched_data["data"]
data_list = data_list + data_chunk
if len(data_list) == int(fetched_data["total_pages"]):
break
else:
page = page +1
...
doRender('dataview.htm',{'data_list':data_list} )
ال data_list
النتائج هي قائمة مرتبة حيث يحتوي العنصر الأول على بيانات رقم الصفحة 1 ، ويحتوي العنصر الأخير على بيانات من أحدث صفحة ؛ هذه data_list
, ، بمجرد استردادها ، يتم تقديمها في عرض.
يعمل هذا النهج 99 ٪ من المرات ولكن في بعض الأحيان ، بسبب 30 ثانية الحد الذي يفرضه Google App Engine ، على العناصر التي تحتوي على العديد من الصفحات التي أحصل عليها المخيفة DeadlineExceededError
. أود أن أعرف ما إذا كان استخدام TaskQueue|مؤجل|عدم التزامن يمكنني تحسين هذه الخوارزمية الموازية بطريقة أو بأخرى.
المحلول
استخدم هذا: http://code.google.com/appengine/docs/python/urlfetch/asynchronousrequests.html
وهو بسيط مثل ذلك:
def handle_result(rpc):
result = rpc.get_result()
# ... Do something with result...
# Use a helper function to define the scope of the callback.
def create_callback(rpc):
return lambda: handle_result(rpc)
rpcs = []
for url in urls:
rpc = urlfetch.create_rpc()
rpc.callback = create_callback(rpc)
urlfetch.make_fetch_call(rpc, url)
rpcs.append(rpc)
# ...
# Finish all RPCs, and let callbacks process the results.
for rpc in rpcs:
rpc.wait()
نصائح أخرى
لقد حلت مع هذا:
chunks_dict = {}
def handle_result(rpc, page):
result = rpc.get_result()
chunks_dict[page] = result["data"]
def create_callback(rpc, page):
return lambda: handle_result(rpc, page)
rpcs = []
while True:
rpc = urlfetch.create_rpc(deadline = 10)
rpc.callback = create_callback(rpc, page)
urlfetch.make_fetch_call(rpc, 'http://www.foo.com/getdata?id=xxx&result=JSON&page=%s' % page)
rpcs.append(rpc)
if page > total_pages:
break
else:
page = page +1
for rpc in rpcs:
rpc.wait()
page_keys = chunks_dict.keys()
page_keys.sort()
for key in page_keys:
data_list= data_list + chunks_dict[key]