TCP重试机制与运用实例
TCP重试机制与运用实例
second60 20180205
1. TCP重试机制简介
在TCP三次握手的过程中,当客户端发送SYN分节之后,如果没有收到服务端返回的确认ACK,那么TCP会在6s后继续发送SYN分节,一直没收到,25s继续发送....在75S后仍然没收到请求,则返回错误。
上面描述了TCP三次握手过程中的重试机制。
1. 发送SYN分节并没收到ACK分节
2. 发送SYN分节后开启超时定时器,如果定时器超时没收到,继续发送
3. 重试有时间限制,这里为75s
TCP发送数据和上面类似。
2. 重试机制分析
2.1什么是重试机制
分析TCP三次握手的重试,可以知道,重试机制是为了本端确认对端对某个处理成功,或者失败。如果成功,则本端做成功处理,如果失败或超时,则重试发送相同请求。
如上图
当一个跨进程服务,在正常情况下,请求,并在规定时间内返回结果。
但由于种种情况,可能会导致发送请求失败,或返回结果时失败。所以在做重试机制。
2.2重试机制触发条件
重试机制主要有三种情况:
1.当发出一个请求时,由于网络故障等,请求没有到达对端服务
2.当发出一个请求时,对端收到请求,并返回,但返回时网络故障,结果没有收到
3.当发出一个请求时,对端收服务由于处理慢,请求太多,或DB慢或其他等因素,导致返回比较慢,在本端收到结果时,已经超时
2.3 重试机制的目的
对于,比较重要的数据或请求,一般都会做重试机制,确保数据或请求对端收到并处理。 以确保数据的正确性。
2.4运用场景
1. 本端必须要确认对端是否处理成功或失败
2. 一般比较重要的数据,如支付,游戏币等操作
2.5 重试机制的实现
下面简单,说下重试机制的实现逻辑,代码自已实现。
本端:
1. 对每发送的请求或数据,拥有唯一ID,标记,时间,状态等
发送记录record_info结构:
id |
记录唯一id |
不会重复,如订单号等 |
retry_times |
重试次数 |
可设多次失败不再重试 |
req_dt |
上一次请求时间 |
|
state |
状态 |
0未成功1成功2失败 |
|
|
|
其他记录信息 |
|
|
2. 对发送后的信息,可以保有存在一个缓存中或redis中或DB中,一般是缓存中。
3. 发送请求后,开始一个定时器(如果是RPC调用,直接用RPC超时)。(可优化成一个定时器)
4. 如时收到回复结果,即可删除缓存记录或修改状态,如果超时,则重新请求。
5. 多次请求失败,放弃请求,并保存记录通知
优化版:
1. 本端只起一个定时器,每段时间轮询缓存或redis或DB中未发送成的且超时的记录,重新请求.
对端:
1. 未处理过的id,处理请求并保存id处理结果
2. 对重复id请求,返回结果即可
4. 例子
4.1 支付系统
支付系统,一个很重要的系统,涉及到充值,金钱交易等。所以每一笔记录都要进行确认。因此,重试机制是必须的。而且支付系统,通知是采用http请求,简单流程如下.
例如上面
1. 用户充值后,支付系统生成了一笔订单,包括订单号,订单状态
eg: order_id:123123121 state:0已下单,未发货
2. 支付系统会通知相应的系统进行发货处理
http://localhost:8080/gameid/pay?order_id=XXX&order_info=XXXX
3. 其他系统处理并返回结果
code |
200成功 其他失败 |
|
msg |
错误原因 |
|
data |
返回结果 |
|
|
|
|
4. 当支付系统,没有收到返回通知,就会一直重试,重试时间可以慢慢加长,由1分钟,3分钟,10分钟,半个钟,一个钟,当重试N次后,会报警,发短信,或邮件等通知。通知相关人员查看问题并处理.
5. 三方系统或游戏商城对相同订单id的请求,只处理一次,并发回处理结果
4.2 游戏币更新
在游戏中,正常都会把游戏的业务逻辑和游戏币操作,会分开,游戏币操作,会独立到一个服务当中,只处理游戏币的操作。不同服务都会连到游戏币服务,进行游戏币的增加或扣除。这里服与服交互,可能采用rpc机制或socket。
游戏币,是存在玩家身上的,当玩家身上的游戏币发生改变时,就会通知游戏币服更新金币。
1. 游戏逻辑服,会缓存玩家的属性和游戏币
2. 当游戏逻辑服发生金币改变时,会通知游戏币服更新玩家游戏币
3. 如果更新不成功,则玩家下次操作时继续更新(或起定时器)
4.3 其他
比较重要的请求
涉及到重要数据的请求
涉及到金钱的请求
订单请求
例子很多,这里就不一一介绍了,用到时,考虑下是不是要做重试机制,虽然重试机制会对逻辑复杂一些,但又是不可缺少的一环。因为重试机制,可以解决很多网络上导致的问题,订单重复扣除的问题等。所以对于重要的请求,一定要用重试机制,对于不那么重要的请求,就可有可无。