繁体   English   中英

“无状态”一致性:不断检查客户端是否仍然连接?

[英]"stateless" consistency: Constantly check if client is still connected?

所以用例是有状态和无状态之间的一条细线——支付API。 因此,当我为支付网关工作时,我们与处理器的连接超过 TCP,因此很容易验证客户端或服务器是否收到了整个消息,但是当您必须提供 REST ZDB974238714CA8DE634A7CE1D03 时,它应该是无状态的,很难知道。 很多场景都可能导致重复事务,例如:

  1. 移动应用程序发送付款请求
  2. 服务器处理消息
  3. 移动应用程序失去连接
  4. 服务器返回响应,但客户端永远不会得到它,所以它不知道它是否成功。
  5. 移动应用再次发送相同的支付请求

一方面,我们可以在两者之间放置一个缓存,基本上锁定相同的事务以防止再次执行(客户端必须提供我们使用的唯一操作/事务 ID),但我觉得这会带来其他复杂性,例如失效。 我想知道是否至少可以使用 .net 中的有线协议来覆盖这种情况?

所以我想尝试这样的事情:

public async Task<IActionResult> Do(CancellationToken abort)
{
    // simulate processing
    await Task.Delay(5_000);

    // see if client is still connected
    if (abort.IsCancellationRequested)
    {
        // if its not, clean up or rollback etc.
        Console.WriteLine("do a rollback");
    }

    return Ok();
}

这样做的问题是,不仅客户端在写入响应时仍然会失去连接,甚至检查本身也可能是错误的。 例如,如果客户端失去连接,那么它永远不会发送断开连接命令,我们仍然认为它们是连接的,直到服务器保持连接失败并且它超时并且到它这样做时,客户端可能已经启动了一个重试。

我想知道是否有办法让我的服务快速发送保持活动(例如 0.5-1 秒间隔),以便我们可以及早失败并回滚。 接下来的问题是:在return Ok()之后是否有检查客户端是否收到了完整的响应? 也许使用可以挖掘 id 并抛出 if(以触发回滚)响应未完全读取的中间件?

当我为支付网关工作时,我们与处理器的连接超过 TCP,因此很容易验证客户端或服务器是否收到了整个消息

TCP 级别存在非常相似的问题。 您可以让客户端发送一个确认消息,但是如果服务器收到它后立即失去连接会发生什么? 服务器将无法发送 TCP ACK,因此据客户端所知,服务器从未收到 ack 消息,它应该重新发送事务。 window 可能更小,但这个问题永远不会完全消失; 这就是分布式计算的本质。

一方面,我们可以在两者之间放置一个缓存,基本上锁定相同的事务以防止再次执行(客户端必须提供我们使用的唯一操作/事务 ID),但我觉得这会带来其他复杂性,例如失效。

标准解决方案是尽可能使请求具有幂等性。 这可以通过缓存来完成; 通常,像 7 或 30 天这样的较长生命周期很容易实现,并且几乎没有遗漏交易的空间。 对于这种“重复数据删除”缓存,我最喜欢的实现是 CosmosDb,因为它高度可靠、快速且支持过期。 如果您在事务中添加时间戳并让客户端拒绝发送太旧的时间戳(或服务器拒绝接受时间戳),则会获得奖励。

那么你的请求是幂等的,如果需要,客户可以整天打电话给他们。

我想知道是否至少可以使用 .net 中的有线协议来覆盖这种情况?

获得一些非常可疑的好处并非没有很多困难。

如果客户端失去连接,那么它永远不会发送断开命令,我们仍然认为它们是连接的,直到服务器保持活动失败并且它超时并且到它这样做时,客户端可能已经开始重试。

是的。

我想知道是否有办法让我的服务快速发送保持活动(例如 0.5-1 秒间隔),以便我们可以及早失败并回滚。

可能不是。 可能获得底层套接字(尽管我对此表示怀疑),然后你可以做一些 hacky 的东西来打开每个套接字的 TCP/IP 保持活动。 但即使这是可能的,它也不会给你带来太多好处。 TCP/IP keepalives 可以被任何中间网络丢弃(它们是 TCP/IP 规范的可选部分)。 即使这是可能的并且它确实有效,那么您只需使用更小的 window 即可发生完全相同的问题 - 问题实际上并没有得到解决

接下来的问题是:在返回 Ok() 之后是否有检查客户端是否收到了完整的响应? 也许使用可以挖掘 id 并抛出 if(以触发回滚)响应未完全读取的中间件?

没有。 HTTP 协议为每个请求提供一个响应; 而已。 从技术上讲,套接字要么知道客户端收到了整个响应,要么知道客户端可能已经或可能没有收到整个响应。 我知道的任何框架都不会向您的应用程序公开该信息,主要是因为它不是真正有用的信息。

TL;DR:幂等性设计。 使用您获得的唯一 ID,并认为自己有幸拥有它。 并非所有系统都这样做。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM