zoukankan      html  css  js  c++  java
  • 【整理】互联网服务端技术体系:可靠性与容错

    综述入口:"互联网应用服务端的常用技术思想与机制纲要"

    引子

    在某种程度上来说,软件的复杂性是应对无处不在的错误所带来的。要想在不可靠的硬件、软件和网络的基础上构建可靠的系统,容错是必不可少的。

    哪里会出错

    要做到更好的容错、健壮和可靠,首先需要全面的梳理可能导致错误的源头和可能性。

    要分析错误源头,则要首先分析应用及流程锁依赖的要素和环节。针对每一个要素和环节,推敲会出错的地方;要了解可预料到的错误,可以看看 Java 库或框架里的各种 Exception 。

    机器节点

    • 磁盘故障、内存耗尽、CPU 100% 占用、掉电;

    网络

    • DNS 故障、机架故障、路由器故障、设备故障、电缆故障;
    • 连接中断、请求排队(延迟)、网络丢包、网络重传、网络拥塞、网络分区。

    时间

    • 很多监控统计依赖于时钟;
    • 数据最终一致性的操作依赖于到达先后顺序;
    • 同一台机器的时钟晶振可能受温度影响而波动;
    • 不同机器上的时钟是不一致的,通过 NTP 协议同步;
    • NTP 协议是经过网络的,这意味着网络的不稳定会影响时钟的同步;
    • “跳秒”现象:1 分钟有 59s 或 61s ;
    • 任务耗时过长,对外部来说就是无响应。

    资源

    • 资源不存在,比如文件不存在;
    • 资源暂时不可用,比如端口已占用;
    • 没有可用资源,比如连接池满;
    • 资源路径已经被移动;
    • 资源访问时的同步死锁。

    数据

    • 不符合预期格式的数据;
    • 脏数据引起解析错误;
    • 不一致的数据引起后继行为错误;
    • 大对象数据引起 FullGC 导致响应不稳定;
    • 错误配置;
    • 非法请求获得正常资源;
    • 恶意代码。

    计算

    • 溢出,不符合运算法则;
    • 除零,无值可表示;
    • 有限精度,浮点计算错误;
    • 逻辑错误,比如越界、不正确的算法。

    设计

    • 设计不足或不合理,容易令人疏忽而导致误操作;
    • 危险操作无确认、无提示,容易造成损失;
    • 少数服从多数原则,达不到多数;
    • Leader 的消息无法被其它节点接收,被其它节点判定为下线。

    流程

    • 中途取消操作;
    • 逆向操作。

    负荷

    • 大流量超出应用承受负荷。

    安全

    • 非授权访问;
    • 数据泄露;
    • 数据被篡改;
    • 访问拒绝。

    并发

    • 数据覆写:访问一个共享资源时,进程 A 获取锁,然后进入了 stop-the-world GC pause ; 进程 B 发现锁已过期,然后申请获得锁,进行数据写操作,接着释放锁;进程 A 结束 GC,进行数据写操作。 进程 A 将 进程 B 的写数据覆盖了。

    拜占庭错误

    • 当分布式系统里的节点要达成共识时,少数节点故意发送错误消息迷惑其它节点,以造成整体错误决策。比如航天领域防电子辐射干扰、多参与者协作和决策。

    健壮性

    健壮性是极为重要的程序质量属性。分为代码健壮性和业务健壮性。健壮性体现在代码和业务上的错误和异常处理上,避免整体失败、数据泄露、不一致、资损等故障。要做出健壮性好的设计和程序,就要预先思考清楚:流程中有哪些可能的错误和异常,每一种对应的处理措施是什么 ? 这样,才能让逻辑思维更加缜密,也是锻炼逻辑思维的一种有效之法。

    • 代码健壮性体现在避免局部失败导致整体失败。常见考虑:参数校验以拦截不合法请求、越界异常捕获、JSON 脏数据异常捕获、类型转换异常捕获、底层异常捕获(连接异常、DB 异常、网络超时异常等)。
    • 业务健壮性体现在业务的闭合环。在整个业务过程中会发生什么异常,导致什么问题(体验或资损问题),如何处理。比如同城异常检测要考虑商家同城呼叫失败后又快递发货的情形。

    容错机制

    思路与方法

    • 设定系统假定,检测系统假定是否成立,然后在系统假定上构建系统;
    • 聚焦高频错误:磁盘故障 > 服务器单机故障 > DNS 故障 > 机架故障 > 路由器重启;
    • 错误提示规范:定义规范一致的错误码和错误消息;
    • 快速失败并记录日志:适用于“请求检测,请求中含有错误或非法数据”的场景;
    • 忽略失败并记录日志:适用于“不影响整体输出且不造成负面影响的极次要地方有点小问题”的场景;
    • 预防策略:避免容易导致错误的做法;
    • 冗余策略:冗余、替换、路由,见高可用部分;
    • 重试策略:幂等;完全重试;补偿重试;
    • 回滚策略:中途取消,重续执行很容易导致脏数据,考虑回滚操作;
    • 故障恢复:监控、检测错误和故障、自动恢复;
    • 乐观锁:递增的 fencing token ,防止过期写操作覆盖已经完成的写操作;

    系统假定

    • 同步模型假定:任何网络延迟、进程暂停、时钟错误都不可能超出某个上限值。即:有限的网络延迟;有限的进程暂停;有限的时钟错误。

    • 部分同步模型假定:在同步模型假定的基础上,允许极少数的无法预测的超上限的网络延迟、进程暂停、时钟错误。

    • 异步模型假定:对时序不做假定,难以预料事件何时发生和动作何时执行。

    • 节点崩溃假定:节点突然失去响应,再也无法正常运行;

    • 节点崩溃-恢复假定:节点可能在任何时候失去响应,在一段时间之后自动恢复并正常运行;易失性存储(比如内存)中的数据丢失,而持久性存储(比如磁盘)中的数据完好;

    • 拜占庭假定:部分节点通过虚假消息欺骗其它节点,从而诱导作出错误的整体决策。

    最常见的系统假定:部分同步模型假定 + 节点崩溃-恢复假定。

    算法的正确性

    • 正确性假定:算法满足某些指定性质。
    • 达成预期结果、安全、活性。

    重试

    • 使操作满足幂等性质;
    • 可以使用失败队列来记录失败的操作及失败信息、失败现场;
    • 完全重试策略:整个操作从头开始执行,适合多读少写的长事务;
    • 补偿重试策略:从失败现场的地方重续执行,适合多写且回滚代价昂贵的长事务;‘
    • 完全重试策略,可指定重试次数;
    • 可采用定时任务重试。
    • 幂等:唯一索引、Token 机制(防页面重复提交)、分布式锁、select+insert、状态机幂等、查询/删除天然幂等。

    可靠性实现

    TCP可靠传输

    • 网络的不可靠性: IP 数据包的丢失、重复、失序;
    • TCP 连接可靠性: 三次握手、四次挥手;
    • TCP 可靠机制:全双工连接、字节流、数据包有序编号、数据校验和、确认、定时器与超时重传、重复丢弃、流量控制(滑动窗口机制)、拥塞控制;
    • TCP 重传机制: 超时重传和快速重传。超时重传依赖于超时时间的设定,快速重传依赖确认包的接收。可以说,选择不同的依赖因子决定了不同的解决途径,也就有不同的优点和缺点。

    超时重传机制

    TCP 发送数据包后,会启动相应的定时器,如果超时 RTO 还没有收到数据确认包,就会重新发送该数据包。

    超时 RTO 的选择非常重要。若 RTO > RTT, 则可能网络利用率低,若 RTO < RTT 则可能拥塞。RTO 的选取基于 RTT 的统计及 BEB (二进制指数退避算法),重传次数及重传最大超时时间(RFC1122)。

    RTO 估计: EWMA RTT 权重估计法(RTO = min(ubound, max(lbound,(SRTT)β)), RTO = (1-2)*SRTT, SRTT ← α(SRTT) + (1 − α) RTTs, α 取 80%-90%, β 取 1.3-2.0),标准估计法(查阅相关文献)。由于 RTO 通常至少是 RTT 的 2 倍,因此超时重传机制容易导致网络利用率不高。

    快速重传机制

    TCP 收到失序数据包后会立即发送确认包,意在告诉发送方迅速发送需要的数据包以填补“包漏洞”(可能存在包丢失)。如果有 dupthresh 个包重新确认了,则很可能存在包丢失,将启动快速重传机制,而不是依赖超时。也就是说,依赖确认包的快速发送和重复确认包来决定是否重传。

    SACK (选择性确认)用来解决数据包重复和失序的问题,总是发送最近收到确认的序列号的范围值。发送者可以推理出最需要发送的未确认的包,并优先发送这些数据包。可以使用位图来检测没有收到的确认序号。快速重传更高效,不过会产生误重传问题。

    重传的性能优化

    • TCP 可以记录每一次的连接和传输,作为性能调优的依据(srtt 和 rttvar),可以做成自适应的;
    • TCP 重传时,可以将多个数据包重组起来一起发送(总大小不能超过 MSS 和 MTU),以提升网络传输效率,也可以减轻重传数据包的二义性。

    TIME_WAIT

    TCP 连接关闭的过程中,客户端在发送服务端 FIN 包的 ACK 之后,进入 TIME_WAIT 状态,需要等待 2MSL 才能关闭。这是为了确保 ACK 可靠到达服务端。

    参考资料


  • 相关阅读:
    Error: unable to connect to node rabbit@mail: nodedown
    flash上传控件跨域
    Nginx配置指定媒体类型文件强制下载
    Nginx反向代理配置可跨域
    日志:using the Connector/J connection property 'autoReconnect=true' to avoid this problem
    web 安全(一)--web简介及 前端技术(js)
    Android 自动化之元素定位 xpath
    Wireshark入门
    自动化测试工具
    Android App 专项测试--压力测试篇(三)
  • 原文地址:https://www.cnblogs.com/lovesqcc/p/14177250.html
Copyright © 2011-2022 走看看