服务端有个任务队列,我提供了一个接口,客户端每调一次,返回队列的头任务后并移除该任务,理想情况下是每个任务都被客户端正常获取到.
但是我用 gevent(wsgi 服务器)+flask 来实现这样的接口时遇到一个问题,就是不能确定是否成功返回了数据,客户端可能压根没收到,万一出现这样的情况,这个任务任务就也被移除并丢失了,比如下面这样的代码.
@app.route("/gettask", methods=['GET', 'POST'])
def gettask():
return 'task' #这里不是函数,我不知道最后没有有成功返回给客户端
1.直接用 socket 开发接口,比如调用其 sendall(),这种是可以判断成功与否的,但这是最后的选择
2.客户端要在成功取到一个任务后再通知服务端,然后接口才移除该任务(这里需要超时机制,客户端也需要确保通知被服务端成功收到了)
3.不管,听天由命了-_-!
1
sagaxu 2017-04-06 11:20:35 +08:00
1. socket 的 sendall 并不能保证对方已经收到,所以你第一个思路行不通
2. 这是比较可行的方式,但是也要考虑一种情况,客户端收到了,但是应答的时候出故障了 |
2
prasanta 2017-04-06 11:29:46 +08:00
这个任务队列是什么东西
|
3
abxialiang OP @sagaxu
socket 层面出现数据丢失的问题可以不考虑了,就认为 TCP 协议是可靠的,否则用第 2 个思路也是死循环了 |
4
abxialiang OP |
5
est 2017-04-06 12:00:17 +08:00
你这个需求跟 flask 、 api 和 wsgi 服务器 都没关系。
新开一个 API 接受回调吧。 |
6
sagaxu 2017-04-06 12:07:58 +08:00 via Android
@abxialiang TCP 协议是可靠的,然而 sendall 只是把数据从应用的 buf 复制到内核 buf 就返回了,还没开始 TCP 层面的传输呢
|
7
abxialiang OP |
8
guyskk 2017-04-06 14:05:41 +08:00
分成 2 个接口:
1. 获取队列头,如果客户端获取失败可以不断重试 2. 根据任务 ID 删除队列中的任务,如果删除失败也可以不断重试 然后就没法保证一个任务只被一个客户端拿到了。。。 |
9
Luckyray 2017-04-06 14:10:22 +08:00 via iPhone
新开 API 接受回调+ 1
|
10
abxialiang OP |
11
Immortal 2017-04-06 14:42:17 +08:00
新开 API 接受回调+ 2
|
12
ryd994 2017-04-07 09:14:47 +08:00 via Android
其实你要关注的不是客户端有没有收到,而是有没有处理
如果客户端收到之后崩了呢?要不要重试? 直接和重试机制做到一起就 OK 了 多少时间内没有收到处理完成的确认就让其他人重试,当然任务本身得是幂等的 |