确保BC交互幂等的一个思路

tech, engineering practice

Background #

客户与服务之间的通信不可避免的存在失败重试,延迟重试。 各式各样的重试之下,如何避免业务流程重复执行呢? 幂等就是一种目前软件工程实践中,较为合理的做法。

Solution #

思路 #

  1. 在客户端请求之前,客户端先向服务器注册一个用于请求的id。
  2. 当服务器收到客户端注册请求时,它会为客户端分配一个唯一的 id。
  3. 服务器创建一个session来存储对注册客户端的请求的响应。 它还跟踪创建session的时间,以便可以丢弃不活动的session。
  4. 对于服务器收到的每个非幂等请求,它在成功执行后将响应存储在客户端session中。
  5. 客户端将客户端标识符与发送到服务器的每个请求一起发送。 客户端还保留一个计数器,为发送到服务器的每个请求分配请求编号。
  6. 当服务器收到请求时,它会检查来自同一客户端的具有给定请求编号的请求是否已被处理。 如果它找到保存的响应,它会向客户端返回相同的响应,而不再次处理请求。

什么时机清除所保存的Response? #

每个客户端存储的请求不能永远存储。那么什么时候清除他们呢? 我认为有以下几种情况

  1. 当客户端告诉服务器,我知道这些请求成功了。
  2. 如果能保证客户端仅在收到前一个请求的响应后才发送下一个请求,则服务器在收到来自客户端的新请求后可以安全地删除所有先前的请求。
    • 部分分布式场景不适用,比如,当客户端有多个同样的请求一起发送时。
  3. 如果服务器知道客户端可以拥有的最大正在进行的请求数,比如[kafka] 最多可以有五个生产者的请求,那么当请求大于5个的时候,就能清理其它所有response。

什么时机清除注册的客户端? #

客户端的session不会永远保存在服务器上。 服务器可以为其存储的客户端session保留最长时间。 客户端定期发送心跳。 如果在此期间没有来自客户端的心跳,则可以删除客户端在服务器上的状态。