如何通过Tornado HTTP服务器上的HTTP使长任务“可取消”?

川岛泉

我已经实现了某种繁重任务的HTTP包装器,我选择了Tornado作为前端服务器框架(这是因为繁重的任务是用Python编写的,而我只是习惯于Tornado)。

目前,我只是从龙卷风的过程中直接调用繁重的任务。我使用jQuery准备了某种基于Web的界面,让它以表单中设置的参数进行AJAX请求。

如您所料,我从网络浏览器中抛出的任务无法取消。我可以取消的唯一方法是向Python进程发送9或15个信号,而这通常不是用户可以做的。

我想通过HTTP请求某种“取消”请求来取消当前正在工作的任务。怎么做到呢?大多数处理繁重任务(例如YouTube中的视频编码)的网络服务在做什么?

石英

实际上,龙卷风Futures不支持取消(docs)。而且,即使使用with_timeout,超时的作业仍在运行,没有什么等待其结果。

唯一的方法,如我如何在超时的情况下如何取消龙卷风中悬挂的异步任务中所述?,是用可以取消的逻辑(带有一些标志或其他任何东西)来实现。

例子:

  • 工作是一个简单的异步睡眠
  • / 列出工作
  • /add/TIME 添加新工作-时间以秒为单位-指定睡眠时间
  • /cancel/ID 取消工作

该代码可能类似于:

from tornado.ioloop import IOLoop
from tornado import gen, web
from time import time

class Job():

    def __init__(self, run_sec):
        self.run_sec = int(run_sec)
        self.start_time = None
        self.end_time = None
        self._cancelled = False

    @gen.coroutine
    def run(self):
        """ Some job

        The job is simple: sleep for a given number of seconds.
        It could be implemented as:
             yield gen.sleep(self.run_sec)
        but this way makes it not cancellable, so
        it is divided: run 1s sleep, run_sec times 
        """
        self.start_time = time()
        deadline = self.start_time + self.run_sec
        while not self._cancelled:
            yield gen.sleep(1)
            if time() >= deadline:
                break
        self.end_time = time()

    def cancel(self):
    """ Cancels job

    Returns None on success,
    raises Exception on error:
      if job is already cancelled or done
    """
        if self._cancelled:
            raise Exception('Job is already cancelled')
        if self.end_time is not None:
            raise Exception('Job is already done')
        self._cancelled = True

    def get_state(self):
        if self._cancelled:
            if self.end_time is None:
                # job might be running still
                # and will be stopped on the next while check
                return 'CANCELING...'
            else:
                return 'CANCELLED'
        elif self.end_time is None:
            return 'RUNNING...'
        elif self.start_time is None:
            # actually this never will shown
            # as after creation, job is immediately started
            return 'NOT STARTED'
        else:
            return 'DONE'


class MainHandler(web.RequestHandler):

    def get(self, op=None, param=None):
        if op == 'add':
            # add new job
            new_job = Job(run_sec=param)
            self.application.jobs.append(new_job)
            new_job.run()
            self.write('Job added')
        elif op == 'cancel':
            # cancel job - stop running
            self.application.jobs[int(param)].cancel()
            self.write('Job cancelled')
        else:
            # list jobs
            self.write('<pre>') # this is so ugly... ;P
            self.write('ID\tRUNSEC\tSTART_TIME\tSTATE\tEND_TIME\n')
            for idx, job in enumerate(self.application.jobs):
                self.write('%s\t%s\t%s\t%s\t%s\n' % (
                    idx, job.run_sec, job.start_time,
                    job.get_state(), job.end_time
                ))


class MyApplication(web.Application):

    def __init__(self):

        # to store tasks
        self.jobs = []

        super(MyApplication, self).__init__([
            (r"/", MainHandler),
            (r"/(add)/(\d*)", MainHandler),
            (r"/(cancel)/(\d*)", MainHandler),
        ])

if __name__ == "__main__":
    MyApplication().listen(8888)
    IOLoop.current().start()

添加情侣职位:

for a in `seq 12 120`; do curl http://127.0.0.1:8888/add/$a; done

然后取消一些...注意-仅需要龙卷风。

这个例子很简单,gen.sleep这将是您繁重的工作当然,并非所有工作都像以可取消的方式实施那样简单。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何创建可取消的任务循环?

来自分类Dev

如何使UdpClient.ReceiveAsync()可取消?

来自分类Dev

如何使UdpClient.ReceiveAsync()可取消?

来自分类Dev

如何使异步池可取消?

来自分类Dev

如何在可取消请求流中重复使用单个异步 Web 服务调用?

来自分类Dev

在服务器上通过 http 请求的 URL 必须是绝对服务器渲染

来自分类Dev

如何为Tornado HTTP服务器创建虚拟主机

来自分类Dev

如何在Apache服务器上启用Http请求?

来自分类Dev

如何通过Apache HTTP服务器让Vaadin Push工作?

来自分类Dev

如何通过代理使流星服务器HTTP.call?

来自分类Dev

如何通过Java HTTP服务器发送图像

来自分类Dev

如何编码图像以通过Python HTTP服务器发送?

来自分类Dev

如何通过代理使流星服务器HTTP.call?

来自分类Dev

如何使Thunderbird通过HTTP代理服务器工作?

来自分类Dev

如何通过HTTP监控mosquitto服务器

来自分类Dev

如何通过按钮使不可取消的进度对话框被取消?

来自分类Dev

如何向服务器指示REST HTTP调用已取消?

来自分类Dev

如何使方法可取消而不使其变得丑陋?

来自分类Dev

如何在Android中设置可取消的超时

来自分类Dev

如何使方法可取消而不使其变得丑陋?

来自分类Dev

如何通过纯HTTP在C#Kestrel Web服务器中启用http2?

来自分类Dev

如何在ubuntu 18.04服务器上安装Oracle http服务器12c?

来自分类Dev

Wowza服务器上的PHP脚本无法通过HTTP身份验证?

来自分类Dev

如何在Android模拟器上向WAMP服务器发出HTTP请求

来自分类Dev

某些服务如何通过修改DNS服务器来应用HTTP代理?

来自分类Dev

如何防止 Cron 任务在服务器上写入文件?

来自分类Dev

如何在Tornado中获得http Referrer?

来自分类Dev

如何在同一服务器上同时发出HTTP和Websocket请求?

来自分类Dev

如何使用python(python -m http.server)在本地服务器上打开html文件?

Related 相关文章

  1. 1

    如何创建可取消的任务循环?

  2. 2

    如何使UdpClient.ReceiveAsync()可取消?

  3. 3

    如何使UdpClient.ReceiveAsync()可取消?

  4. 4

    如何使异步池可取消?

  5. 5

    如何在可取消请求流中重复使用单个异步 Web 服务调用?

  6. 6

    在服务器上通过 http 请求的 URL 必须是绝对服务器渲染

  7. 7

    如何为Tornado HTTP服务器创建虚拟主机

  8. 8

    如何在Apache服务器上启用Http请求?

  9. 9

    如何通过Apache HTTP服务器让Vaadin Push工作?

  10. 10

    如何通过代理使流星服务器HTTP.call?

  11. 11

    如何通过Java HTTP服务器发送图像

  12. 12

    如何编码图像以通过Python HTTP服务器发送?

  13. 13

    如何通过代理使流星服务器HTTP.call?

  14. 14

    如何使Thunderbird通过HTTP代理服务器工作?

  15. 15

    如何通过HTTP监控mosquitto服务器

  16. 16

    如何通过按钮使不可取消的进度对话框被取消?

  17. 17

    如何向服务器指示REST HTTP调用已取消?

  18. 18

    如何使方法可取消而不使其变得丑陋?

  19. 19

    如何在Android中设置可取消的超时

  20. 20

    如何使方法可取消而不使其变得丑陋?

  21. 21

    如何通过纯HTTP在C#Kestrel Web服务器中启用http2?

  22. 22

    如何在ubuntu 18.04服务器上安装Oracle http服务器12c?

  23. 23

    Wowza服务器上的PHP脚本无法通过HTTP身份验证?

  24. 24

    如何在Android模拟器上向WAMP服务器发出HTTP请求

  25. 25

    某些服务如何通过修改DNS服务器来应用HTTP代理?

  26. 26

    如何防止 Cron 任务在服务器上写入文件?

  27. 27

    如何在Tornado中获得http Referrer?

  28. 28

    如何在同一服务器上同时发出HTTP和Websocket请求?

  29. 29

    如何使用python(python -m http.server)在本地服务器上打开html文件?

热门标签

归档