处理连接丢失
RPC 调用完成后,连接不会关闭;它标记为免费。 因此,当连接位于池中时,服务器可能会关闭或网络连接在调用期间或两次调用之间丢失。 根据策略,RPC 运行时仅在满足以下两个条件时重新尝试这些调用:
- 服务器无法执行调用,或者调用是幂等的。
- 客户端能够以高效性能的方式实现重试。
以下段落扩展并阐明了两个条件。
幂等调用是可以在服务器上多次执行的调用,而不会产生不良的副作用。 例如,使用 RPC 调用来查询给定帐户的银行余额是幂等的。 如果由于连接丢失而执行此调用两次,则不会造成损害。 幂等调用的另一个示例是更改数据库中客户的地址。 执行两次是正常的,因为第二次执行只是将已存在的地址替换为相同的地址。 像“从帐户 xyz 中减去五十美元”这样的操作不是幂等的。 网络连接丢失不应导致多次执行此类调用。
为安全起义,RPC 运行时将所有调用视为非幂等。 ncacn_ip_tcp不支持 [幂等] 属性,并且将被忽略。 因此,上述列表中的第一个条件将缩减为 无法执行调用的服务器。
在许多情况下,RPC 运行时无法最终确定调用尚未在服务器上执行。 在这种情况下,客户端不会重试执行调用。
以下示例演示了 RPC 运行时何时重试或不重试调用:
服务器已重新启动。
在重新启动后未对其执行任何先前调用的接口上进行简单的无安全性 RPC 调用。 由于未对此接口进行调用,RPC 运行时首先尝试协商接口的使用。 它使用池中的连接发送数据包。 由于服务器已重新启动,并且连接不再有效,因此会返回错误。 由于客户端 RPC 运行时尚未开始发送实际调用的数据,因此客户端确定服务器不可能对这些数据执行。 因此,它会关闭连接并在池中查找另一个连接。 如果找不到连接,则会打开一个新连接,并再次尝试协商使用该接口。 如果此操作成功,则调用 (即重试,因为) 启动调用之前检测到失败。
使用隐私级别安全 (加密) 的 RPC 调用是在与已协商的安全上下文的连接上进行的。
为了确保高效性能,RPC 运行时通过明文数据) 加密封送内联数据包 (。 如果尝试发送数据失败,RPC 运行时将无法重试调用,因为明文数据已被加密数据覆盖,并且无法使用新的安全上下文重新加密数据。 因此,不会重试。
发送非第一个片段失败。
不会重试,因为 RPC 运行时可能会选择在第一个片段完成后放弃第一个片段的内容,并且无法重试发送第一个片段。
RPC 请求已发送。
服务器中止连接。 不会尝试重试,因为 RPC 无法识别服务器是否已收到调用并开始执行该调用。
如果服务器使用动态终结点,则 RPC 不会在重试期间重新解析该终结点。 这意味着,如果服务器关闭并恢复,它可能驻留在不同的终结点上,并且 RPC 不会在重试调用时以透明方式重新解析该终结点。 若要强制重新解析终结点,RPC 客户端应在重试调用之前调用 RpcBindingReset 。
在许多情况下,如果 RPC 客户端可以确定调用是否是幂等的,或者它是否保留 RPC 丢弃的数据,它可能会选择在 RPC 之上构建重试机制。
注意
如果服务器是群集,并且群集的不同节点运行不同版本的服务器软件,则 RPC 重试可能会在故障转移时将调用登陆到群集的不同节点上,并可能在服务器的不同版本上。 在此类部署方案中,请确保客户端不依赖特定版本的服务器软件来执行给定的调用。 如果确实如此,客户端应在 RPC 之上构建一种机制,用于检测和处理此类情况。