V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
tihiro
V2EX  ›  Python

如何提高轮询查询效率

  •  
  •   tihiro · 2022-04-29 19:54:56 +08:00 · 3187 次点击
    这是一个创建于 698 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题描述: 创建任务之后需要调别的平台的接口去查询结果。任务执行时间未知,调接口结果有可能返回任务正在进行中。外部原因,服务端不推送消息给我,那么怎么设计能使轮询效率提高呢? 单线程:轮询时间间隔太长导致任务结果不能及时返回更新;太短 cpu 利用率高,且目前用队列来做的话,会被反复放入队列,查询结果出不来。

    16 条回复    2022-05-03 09:11:34 +08:00
    cz5424
        1
    cz5424  
       2022-04-29 20:11:17 +08:00 via iPhone
    轮询换 websocket
    cxytz01
        2
    cxytz01  
       2022-04-29 20:37:50 +08:00
    1.你这个服务创建任务之后,就啥也不用干。
    2.你这个服务提供一个接口( http ),让别人调你,然后你去调别的平台的接口查询结果。
    3.你需要一个服务,你去这个服务配置多久多久去调用 2 的接口。

    如果你的服务是异步的、协程实现、多线程的,那就不会存在单线程的问题。
    轮询的频率随你控制。


    google 一下:定时任务调度器
    documentzhangx66
        4
    documentzhangx66  
       2022-04-29 21:55:11 +08:00
    感觉你的思路很乱,建议:

    1.把需求,再细化地写清楚。
    2.画个流程图,贴出来。用图床就行。
    darkengine
        5
    darkengine  
       2022-04-29 22:35:05 +08:00
    按照描述,可以优化的就只有选择最优的轮询间隔了。可以 8s ,4s ,2s ,1s ,1s, 1s 这样的可变间隔去查询第三方平台的接口,跑一段时间之后根据成功查询到结果所需时长来修改间隔。
    twing37
        6
    twing37  
       2022-04-30 01:11:39 +08:00
    看到 task ,考虑时间轮或者最小堆的任务时间管理吗? 其他的就是你的时间优化策略了.没别的好办法
    jinliming2
        7
    jinliming2  
       2022-04-30 09:07:07 +08:00 via iPhone   ❤️ 1
    先说你调的这个“别的平台”的服务是否可以按你的需要修改?不可以的话,你又用不了推送,那就只能短轮询了,要提高效率只能缩短轮询时间间隔,避免 CPU 占用的话,可以根据 CPU 负载动态调整轮询时间间隔,应该也只能这样了。

    如果这个服务平台可以根据你的需求做修改调整,首选肯定是支持推送,回调你的 webhook ,但由于网络原因( NAT 之类的)不能做 webhook 推送的话,也可以考虑支持 websocket ,建立 websocket 来进行推送。或者另一种修改思路是把短轮询接口改成长轮询,即你本地请求后,服务端不作响应,直到服务端处理完毕后立即响应,如果服务端在请求超时时间内(几十秒)仍然没有处理完毕,则响应一个未完成的响应,你收到后立即重试就行。这样虽然还是小间隔的轮询请求,但是请求时长被放大到几十秒,属于 io 时间不消耗 CPU ,也会比短轮询更实时。
    IvanLi127
        8
    IvanLi127  
       2022-04-30 12:44:50 +08:00 via Android
    单独跑一个轮询转推送的服务,让这个服务成为适配器,以后上游服务能改推送了你也能很快地接入,如果上游不改,那压力也传不到你这。
    tihiro
        9
    tihiro  
    OP
       2022-04-30 14:37:03 +08:00
    @twing37 感谢回复。考虑了时间轮,暂时没有实现。不是定时任务,不知道时间轮适不适用。
    tihiro
        10
    tihiro  
    OP
       2022-04-30 14:39:19 +08:00
    @darkengine 谢谢回复,时间间隔的设置是一个问题,另外一个就是一次取多少个的问题。另外一个问题是不知道 python 的多线程效率是否比单线程高。
    tihiro
        11
    tihiro  
    OP
       2022-04-30 14:42:59 +08:00
    @jinliming2
    @cz5424 感谢二位的回复。多谢提醒,差点忘了 websocket 。
    tramm
        12
    tramm  
       2022-04-30 14:49:51 +08:00
    超时时间设长一点, 使用 Future, 返回结果了再调用 Future.get()
    回复完发现是 Python 不知道有没有 Future
    lmshl
        13
    lmshl  
       2022-04-30 17:45:23 +08:00

    大意如此,coroutine 不会消耗多少 CPU
    tihiro
        14
    tihiro  
    OP
       2022-05-02 10:16:59 +08:00
    @tramm 服务端会立马响应,但是结果是任务处理中。
    tihiro
        15
    tihiro  
    OP
       2022-05-02 10:17:27 +08:00
    @lmshl 问题是用的 py2
    tramm
        16
    tramm  
       2022-05-03 09:11:34 +08:00
    @tihiro 那把任务处理结果当 Future 的结果?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4286 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 10:13 · PVG 18:13 · LAX 03:13 · JFK 06:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.