质量属性战术——可用性战术
可用性战术:
可用性与系统故障及其相关后果有关。当系统不再提供其规范中所说明的服务时,就出现了系统故障。
所关注的方面有:
- 如何检测系统故障
- 系统故障发生的频度
- 出现故障时会发生什么情况
- 允许系统有多长时间非正常运行
- 什么时候可以安全地出现故障
- 如何防止故障的发生以及故障时要求进行哪种通知
一般将系统可用性定义为:
a = 平均正常工作时间 / (平均正常工作时间+平均修复时间)
从这个公式中我们得到了像99.9%的可用性、0.1%的故障率这样的概念。
在计算可用性时,通常不考虑预定的停机时间(即停止服务),因为根据定义是”不需要“系统的。这就导致会出现这种情况:系统停止运行,用户等待系统提供服务,但因为停机时间是预定的,因此不计入故障时间,也就不会影响可用性的数值。
错误检测
-
命令/响应
一个组件发生一个命令,并希望在预定义的时间内收到一个来自审查组件的响应。 -
心跳
一个组件定期发出一个心跳消息,另一个组件收听该消息。 -
异常
当组件出现异常时就可以认为组件出现了错误。
错误恢复
-
表决
运行在冗余处理器上的每个进程都具有相等的输入,它们计算发送给表决者的一个简单输出值。如果表决者检测到单处理器的异常行为,那么,就中止这一行为。 -
主动冗余
所有的冗余组件都以并行的方式对事件做出响应。仅使用一个组件的响应,丢弃其余组件的响应。错误发生时,使用该战术的系统的停机时间通常是几毫秒,因为备份是最新的,所以恢复所需要的时间就是切换时间。 -
被动冗余(暖重启/双冗余/三冗余)
一个组件对事件做出响应,并通知其他组件必须进行状态更新。当错误发生时,在继续提供服务前,系统必须首先确保备用状态是最新的。
-
备件
备用是计算平台配置用于更换各种不同的故障组件。出现故障时,必须将其重新启动为适当的软件配置,并对其状态进行初始化。 -
shadow操作
以前出现故障组件可以在短时间内以"shadow模式"运行,以确保在恢复该组件之前,模仿工作组件的行为。 -
状态再同步
主动和被动冗余战术要求所恢复的组件在重新提供服务前更新其状态。更新方法取决于可以承受的停机时间、更新的规模以及更新所要求的消息的数量。如果可能的话,最好用一条消息包含该状态。增量式状态更新和两个增量之间的服务周期会导致复杂的软件。
检查点就是记录所创建一致状态,或者是定期进行,或者是对具体事件做出响应。有时系统会以一种不同寻常的方式出现故障,可检测到其状态不一致。在这种情况下,应该使用 上一个一致检查点和拍了快照后所发生的事务的日志来恢复系统。
错误预防
-
从服务中删除
该战术从操作中删除了系统的一个组件,以执行某些活动来防止预期发生的故障。一个示例就是重新启动组件,以防止内存泄漏导致故障的发生。 -
事务
事务就是绑定几个有序的步骤,以能够立刻撤销整个绑定。如果进程中的一个步骤失败的话,可以使用事务来防止任何数据受到影响,还可以使用事务来防止访问相同数据的几个同时线程之间发生冲突。 -
进程监视器
一旦检测到进程中存在错误,监视进程就可以删除非执行进程,并为该进程创建一个新的实例,就像在备件战术中一样,初始化为某个适当的状态。
在开发时推迟绑定时间:
public class DBUtil { public static Connection getConnection() { try { Class.forName("com.mysql.jdbc.Driver").newInstance(); } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { e.printStackTrace(); } String user = "root"; String password = "root"; String url = "jdbc:mysql://localhost:3306/pachong"; Connection connection = null; try { connection = DriverManager.getConnection(url,user,password); System.out.println("ok"); } catch (SQLException e) { e.printStackTrace(); } return connection; } public static void close(Connection connection ) { try { if (connection != null) { connection.close(); } } catch (SQLException e) { e.printStackTrace(); } } public static void close(PreparedStatement preparedStatement ) { try { if (preparedStatement != null) { preparedStatement.close(); } } catch (SQLException e) { e.printStackTrace(); } } public static void close(ResultSet resultSet ) { try { if (resultSet != null) { resultSet.close(); } } catch (SQLException e) { e.printStackTrace(); } }