2011-03-23 14 views
6

En algún código que estoy escribiendo para GAE, necesito realizar periódicamente un GET en una URL en otro sistema, básicamente 'haciendo ping' y no estoy muy preocupado si la solicitud falla, se agota o tiene éxito .URLfetch asincrónico cuando no nos importa el resultado? [Python]

Como básicamente quiero 'disparar y olvidar' y no ralentizar mi propio código esperando la solicitud, estoy usando un urlfetch asincrónico, y no llamando a get_result().

En mi registro de recibo una advertencia:

encontrado 1 solicitud (s) de RPC sin cumplir ninguna respuesta (presumiblemente debido a los tiempos de espera u otros errores)

Me estoy perdiendo de una manera obviamente mejor que hacer ¿esta? Una Task Queue o una tarea diferida me parece (como a mí) una sobrecarga en esta instancia.

Cualquier entrada sería apreciada.

+0

Estoy suponiendo que esto es Python y Java no? – jiggy

+0

Estás en lo correcto. He actualizado la pregunta. Buena atrapada. –

+0

Debe instrumentar para determinar si la operación URLFetch se está completando, y si lo hace, si eso ocurre antes o después de que su solicitud regrese a la persona que llama. Creo que encontrará que * does * finish, y que 'wait' sucede implícitamente * después * de que la solicitud original devuelva su resultado. Sin embargo, no he encontrado documentación explícita para esto en ninguna parte, por lo que el comportamiento puede estar sujeto a cambios. – technomage

Respuesta

6

Una tarea de cola de tareas es su mejor opción aquí. El mensaje que está viendo en el registro indica que la solicitud está esperando a que se complete su URLFetch antes de regresar, por lo que esto no ayuda. Usted dice que una tarea es 'exagerada', pero en realidad, son muy livianas y definitivamente la mejor manera de hacerlo. Diferido incluso le permitirá diferir la llamada de búsqueda directamente, en lugar de tener que escribir una función para llamar.

2

¿Cuánto tiempo lleva completar la async_url_fetch y cuánto tiempo lleva su respuesta?

Aquí hay un posible enfoque para aprovechar la forma en que funciona la API en Python.

Algunos puntos a considerar.

  • Muchos servidores web y proxies inversos no cancelarán una solicitud una vez que se haya iniciado. Por lo tanto, si su servidor remoto que está haciendo ping envía la solicitud pero tarda mucho tiempo en repararla, use una fecha límite en su create_rpc (fecha límite = X) de modo que X regrese debido a un tiempo de espera excedido. El ping aún puede tener éxito. Esta técnica también funciona contra appengine.

  • GAE RPC

    • RPC después de ser complementada a través de make_call/make_fetch_call son en realidad sólo enviados una vez que uno de ellos se atendió.
    • También se llamará a cualquier archivo rpc recién terminado cuando finalice el esperado en ese momento.
    • Puede crear un archivo async_urlfetch rpc y ponerlo en cola usando make_fetch_call tan pronto como sea posible en el manejo de su solicitud, no espere todavía.
    • Realice el trabajo de publicación de la página real, como llamadas de Memcache/almacén de datos para iniciar el trabajo. La primera llamada a una de estas realizará una espera que enviará su async_urlfetch.
    • Si el urlfetch se completa durante esta otra actividad, se llamará a la devolución de llamada en el urlfetch, lo que le permitirá manejar el resultado.
    • Si llama a get_result() bloqueará en wait() hasta la fecha límite o se devolverá a menos que el resultado esté listo.

Para recapitular.

Prepare el url_fetch de larga ejecución con una fecha límite razonable y devolución de llamada. Encuéntralo usando make_fetch_call. Haz el trabajo que deseas para la página. Devuelva la página independientemente de si la url_fetch se completó o finalizó y sin esperarla.

La capa de RPC subyacente en GAE es totalmente asíncrona, parece haber una manera más sofisticada de elegir lo que desea esperar en el trabajo.

Estos ejemplos usan sleep y url_fetch en una segunda instancia de la misma aplicación.

Ejemplo de espera() enviar el trabajo RPC:

class AsyncHandler(RequestHandler): 

    def get(self, sleepy=0.0): 
     _log.info("create rpc") 
     rpc = create_rpc() 
     _log.info("make fetch call") 
     # url will generate a 404 
     make_fetch_call(rpc, url="http://<my_app>.appspot.com/hereiam") 
     _log.info("sleep for %r", sleepy) 
     sleep(sleepy) 
     _log.info("wait") 
     rpc.wait() 
     _log.info("get_result") 
     rpc.get_result() 
     _log.info("return") 
     return "<BODY><H1>Holla %r</H1></BODY>" % sleepy 

Esperar llamada después de dormir durante 4 segundos muestra el envío de

2011-03-23 17:08:35.673 /delay/4.0 200 4093ms 23cpu_ms 0kb Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.151 Safari/534.16,gzip(gfe) 
I 2011-03-23 17:08:31.583 create rpc 
I 2011-03-23 17:08:31.583 make fetch call 
I 2011-03-23 17:08:31.585 sleep for 4.0 
I 2011-03-23 17:08:35.585 wait 
I 2011-03-23 17:08:35.663 get_result 
I 2011-03-23 17:08:35.663 return 
I 2011-03-23 17:08:35.669 Saved; key: __appstats__:011500, part: 48 bytes, full: 4351 bytes, overhead: 0.000 + 0.006; link: http://<myapp>.appspot.com/_ah/stats/details?tim 
2011-03-23 17:08:35.636 /hereiam 404 9ms 0cpu_ms 0kb AppEngine-Google; (+http://code.google.com/appengine; appid: s~<myapp>),gzip(gfe) 

asíncrono envió llamada.

E 2011-03-23 17:08:35.632 404: Not Found Traceback (most recent call last): File "distlib/tipfy/__init__.py", line 430, in wsgi_app rv = self.dispatch(request) File "di 
I 2011-03-23 17:08:35.634 Saved; key: __appstats__:015600, part: 27 bytes, full: 836 bytes, overhead: 0.000 + 0.002; link: http://<myapp>.appspot.com/_ah/stats/details?time 

Mostrando un memcache RPC espera para iniciar el trabajo.

class AsyncHandler(RequestHandler): 

    def get(self, sleepy=0.0): 
     _log.info("create rpc") 
     rpc = create_rpc() 
     _log.info("make fetch call") 
     make_fetch_call(rpc, url="http://<myapp>.appspot.com/hereiam") 
     _log.info("sleep for %r", sleepy) 
     sleep(sleepy) 
     _log.info("memcache's wait") 
     memcache.get('foo') 
     _log.info("sleep again") 
     sleep(sleepy) 
     _log.info("return") 
     return "<BODY><H1>Holla %r</H1></BODY>" % sleepy 

AppEngine Prod Log:

2011-03-23 17:27:47.389 /delay/2.0 200 4018ms 23cpu_ms 0kb Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.151 Safari/534.16,gzip(gfe) 
I 2011-03-23 17:27:43.374 create rpc 
I 2011-03-23 17:27:43.375 make fetch call 
I 2011-03-23 17:27:43.377 sleep for 2.0 
I 2011-03-23 17:27:45.378 memcache's wait 
I 2011-03-23 17:27:45.382 sleep again 
I 2011-03-23 17:27:47.382 return 
W 2011-03-23 17:27:47.383 Found 1 RPC request(s) without matching response (presumably due to timeouts or other errors) 
I 2011-03-23 17:27:47.386 Saved; key: __appstats__:063300, part: 66 bytes, full: 6869 bytes, overhead: 0.000 + 0.003; link: http://<myapp>.appspot.com/_ah/stats/details?tim 
2011-03-23 17:27:45.452 /hereiam 404 10ms 0cpu_ms 0kb AppEngine-Google; (+http://code.google.com/appengine; appid: s~<myapp>),gzip(gfe) 

asíncrono de extracción de URL distribuyen cuando memcache.get a wait()

E 2011-03-23 17:27:45.446 404: Not Found Traceback (most recent call last): File "distlib/tipfy/__init__.py", line 430, in wsgi_app rv = self.dispatch(request) File "di 
I 2011-03-23 17:27:45.449 Saved; key: __appstats__:065400, part: 27 bytes, full: 835 bytes, overhead: 0.000 + 0.002; link: http://<myapp>.appspot.com/_ah/stats/details?time 
+0

Esta no es una solución simple, pero tiene la intención de proporcionar algo de reflexión. – kevpie

+0

Buen punto sobre los tiempos de espera. Sin embargo, estoy bastante seguro de que está equivocado acerca de que las RPC solo se envíen una vez que se ha llamado a la espera, eso solo se aplica en el dev_appserver según mi leal saber y entender. –

+0

@Nick, tuve que verificarlo dos veces. La documentación en la fuente actualmente puede predecir el futuro o ser ligeramente engañosa. Esto es algo a lo que casi nadie se enfrentaría a menos que estén seriamente deprimidos al hacer llamadas asíncronas. Tuve un sueño después de construir asynctools para crear un solucionador de fragmentos de página asíncrono que hizo todo en paralelo. Hace un año, estaba trabajando en una herramienta que realizaba docenas de llamadas API entre facebook/twitter/linkedin con múltiples claves de Oauth/respaldos públicos en tiempo real. El paralelismo que proporciona la capa GAE RPC es simplemente asombroso. – kevpie

Cuestiones relacionadas