控制器Action执行期间客户端连接丢失会发生什么?
不同场景下控制器Action客户端断连的行为说明
场景1:Action内调用修改资源状态的REST API中途断连
- 绝大多数Web框架的默认逻辑是:Action代码一旦开始执行,除非代码主动检测客户端连接状态,否则不会因为客户端断连直接中断运行
- 你调用的修改资源状态的REST API只要已经将请求发至对端服务,对端就会正常执行状态修改逻辑,不会因为你这边客户端断连就自动回滚,除非你自己在代码里实现了断连检测+分布式事务补偿的逻辑
- 这个阶段断连大概率不会主动抛出异常,所有业务逻辑会正常跑完,只是最终要返回给客户端的响应结果会被直接丢弃
场景2:加载大量数据作为Stream返回中途断连
- 这个场景的行为取决于Stream实现和框架的响应写入逻辑:
- 如果你是先把所有数据全量加载到内存,再包装成Stream返回:断连发生在数据加载阶段的话,加载逻辑会正常跑完,直到框架尝试往响应流写数据时才会检测到连接已断开,此时会抛出类似
Connection reset by peer/Broken pipe的IO异常 - 如果你用的是边读边写的真流式加载逻辑:断连后框架下次尝试往响应流写数据时就会触发IO异常,后续的数据加载逻辑会因为异常终止
- 如果你是先把所有数据全量加载到内存,再包装成Stream返回:断连发生在数据加载阶段的话,加载逻辑会正常跑完,直到框架尝试往响应流写数据时才会检测到连接已断开,此时会抛出类似
- 异常如果没有被手动捕获,框架会默认打印错误日志,不会继续执行后续的写入逻辑
场景3:返回自行处理读写逻辑的1GB电影Stream中途断连
- 这种自定义Stream的场景,断连触发的IO异常会在你调用Stream的
Read/Write方法时抛出 - 如果你在自定义Stream逻辑里捕获了这个异常,可以自行终止资源读取、释放文件句柄;如果没捕获,异常会往上抛到框架层,直接终止整个响应流程,不会继续把剩下的电影数据读完
- 不存在把整个1GB文件全部读完再丢到/dev/null的情况,只要触发下一次读写操作就会感知到连接断开,直接终止流程
常见误区说明
不是所有断连都会立刻被感知到,TCP连接的断开检测本身存在延迟。如果你的逻辑在断连后长时间没有进行响应流的写入操作,代码会继续正常运行,直到第一次写入操作时才会抛出异常。如果你的代码全程没有往响应流写数据的操作(比如纯后台调用第三方接口的逻辑),你全程都感知不到客户端断连,所有代码会正常执行完毕。
内容的提问来源于stack exchange,提问作者jjaskulowski
相关产品推荐
相关产品推荐

