所有可能出错的事情一定会出错。
作为开发者,我们的核心任务是构建可靠的系统,即使系统面临各种出错可能,也需要完成预定工作(确保满足用户期望)
一 故障与部分失效
- 故障处理是软件设计的重要组成部分。
最好仔细考虑各种可能的出错情况,包括那些小概率故障,然后尝试认为构造这种测试场景来充分检测系统行为。
- 在分布式系统中,怀疑,悲观和偏执狂才能生存。
(1)单节点
如果发生了某种内部错误,我们宁愿使计算机全部崩溃,而不是返回一个错误的结果,错误的结果往往更难处理。
(2)云计算
对于高性能计算,通常会定期对任务状态进行快照,然后保存在持久存储上,当某节点出现故障,解决方案是简单地停止整个集群的任务; 等故障节点修复之后,从最近的快照检查点继续执行。
从这一点看,它将局部失效升级为整体失效
二 不可靠的网络
(1)如何设置超时时间?
1. 普通做法
实验。
先在多台机器上,多次测量网络往返时间,以确定延迟的大概范围; 然后结合应用特点,在故障检测与过早超时时风险之间选择一个合适的中间值。
2. 更好的做法
超时设置并不是一个不变的常量
根据最新的响应时间分布来自动调整。
-
可以用
Phi Accrual
故障检测器完成,该检测器目前已在Akka
和Cassandra
中使用 -
TCP的重传超时也采用了类似的机制
三 不可靠的时钟
网络上的每台机器都有自己的时钟硬件设备,通常是石英晶体振荡器
即每台机器都维护自己本地的时间版本,可能比其他机器稍快或更慢
可以在一定程度上同步机器之间的时钟,最常用的方法是:
网络时间协议(Network Time Protocol, NTP),它可以根据一组专门的时间服务器来调整本地时间。
(1)一个线程可能会暂停这么长时间嘛?
- 垃圾收集器(GC)
有时运行期间会暂停所有正在运行的线程
-
在虚拟化环境中,可能会暂停虚拟机
-
终端机休眠或关机
-
线程上下文切换时
-
应用程序执行同步磁盘操作,则线程可能暂停并等待磁盘 I/O 完成
-
如果操作系统配置了基于磁盘的内存交换分区,内存访问可能触发缺页中断,进而需要从磁盘中加载内存页
-
通过发送
SIGSTOP
信号来暂停UNIX进行
参考资料
DDIA