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
abxialiang
V2EX  ›  Python

flask 框架开发 api 接口,当 wsgi 服务器层返回失败时该如何处理业务.

  •  
  •   abxialiang · 2017-04-06 11:01:16 +08:00 · 2602 次点击
    这是一个创建于 2781 天前的主题,其中的信息可能已经有所发展或是发生改变。

    业务是这样:

    服务端有个任务队列,我提供了一个接口,客户端每调一次,返回队列的头任务后并移除该任务,理想情况下是每个任务都被客户端正常获取到.

    但是我用 gevent(wsgi 服务器)+flask 来实现这样的接口时遇到一个问题,就是不能确定是否成功返回了数据,客户端可能压根没收到,万一出现这样的情况,这个任务任务就也被移除并丢失了,比如下面这样的代码.

    @app.route("/gettask", methods=['GET', 'POST'])
    def gettask():
        return 'task' #这里不是函数,我不知道最后没有有成功返回给客户端
    

    目前思路:

    1.直接用 socket 开发接口,比如调用其 sendall(),这种是可以判断成功与否的,但这是最后的选择

    2.客户端要在成功取到一个任务后再通知服务端,然后接口才移除该任务(这里需要超时机制,客户端也需要确保通知被服务端成功收到了)

    3.不管,听天由命了-_-!

    12 条回复    2017-04-07 09:14:47 +08:00
    sagaxu
        1
    sagaxu  
       2017-04-06 11:20:35 +08:00
    1. socket 的 sendall 并不能保证对方已经收到,所以你第一个思路行不通
    2. 这是比较可行的方式,但是也要考虑一种情况,客户端收到了,但是应答的时候出故障了
    prasanta
        2
    prasanta  
       2017-04-06 11:29:46 +08:00
    这个任务队列是什么东西
    abxialiang
        3
    abxialiang  
    OP
       2017-04-06 11:55:19 +08:00
    @sagaxu
    socket 层面出现数据丢失的问题可以不考虑了,就认为 TCP 协议是可靠的,否则用第 2 个思路也是死循环了
    abxialiang
        4
    abxialiang  
    OP
       2017-04-06 11:56:00 +08:00
    @prasanta
    可以理解为
    [1,2,3,4,5,6,7,8,9,....]
    est
        5
    est  
       2017-04-06 12:00:17 +08:00
    你这个需求跟 flask 、 api 和 wsgi 服务器 都没关系。

    新开一个 API 接受回调吧。
    sagaxu
        6
    sagaxu  
       2017-04-06 12:07:58 +08:00 via Android
    @abxialiang TCP 协议是可靠的,然而 sendall 只是把数据从应用的 buf 复制到内核 buf 就返回了,还没开始 TCP 层面的传输呢
    abxialiang
        7
    abxialiang  
    OP
       2017-04-06 13:27:29 +08:00
    @est
    @sagaxu
    看来需要在应用层增加确认
    guyskk
        8
    guyskk  
       2017-04-06 14:05:41 +08:00
    分成 2 个接口:
    1. 获取队列头,如果客户端获取失败可以不断重试
    2. 根据任务 ID 删除队列中的任务,如果删除失败也可以不断重试

    然后就没法保证一个任务只被一个客户端拿到了。。。
    Luckyray
        9
    Luckyray  
       2017-04-06 14:10:22 +08:00 via iPhone
    新开 API 接受回调+ 1
    abxialiang
        10
    abxialiang  
    OP
       2017-04-06 14:38:56 +08:00
    @guyskk
    @Luckyray
    知道怎么做了,谢谢各位大佬
    Immortal
        11
    Immortal  
       2017-04-06 14:42:17 +08:00
    新开 API 接受回调+ 2
    ryd994
        12
    ryd994  
       2017-04-07 09:14:47 +08:00 via Android
    其实你要关注的不是客户端有没有收到,而是有没有处理
    如果客户端收到之后崩了呢?要不要重试?
    直接和重试机制做到一起就 OK 了
    多少时间内没有收到处理完成的确认就让其他人重试,当然任务本身得是幂等的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   939 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 21:47 · PVG 05:47 · LAX 13:47 · JFK 16:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.