一般将系统可用性定义为:a = 平均正常工作时间 / (平均正常工作时间+平均修复时间)
错误检测
- 命令/响应
一个组件发生一个命令,并希望在预定义的时间内收到一个来自审查组件的响应。
命令/响应在ajax中有所应用,ajax有专门的success方法和error方法来对发出的请求做出响应。
例如ajaxPost请求
var xhr = new XMLHttpRequest();
xhr.open("post","validate.php");
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send("username="+name);
xhr.onreadystatechange = function(){
// 判断服务器是否响应,判断异步对象的响应状态
if(xhr.status == 200 && xhr.readyState == 4){
document.querySelector(".showmsg").innerHTML = xhr.responseText;
}
}
- 心跳
一个组件定期发出一个心跳消息,另一个组件收听该消息。
最常见的就是try{}catch{}finally{}以及if语句进行判断
- 异常
当组件出现异常时就可以认为组件出现了错误。该部分我最常用的就是try{} catch{} finally{} 进行错误的捕获,以及js函数对对不符合要求的填报内容进行错误的抛出及提示。与此同时数据库的事务会进行回滚,回到事务未开始的状态。
public static void close(Connection conn, Statement st, ResultSet rs) {
try {
if (conn != null) {
conn.close();
}
if (st != null) {
st.close();
}
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
错误恢复
- 表决
运行在冗余处理器上的每个进程都具有相等的输入,它们计算发送给表决者的一个简单输出值。如果表决者检测到单处理器的异常行为,那么,就中止这一行为。 - 主动冗余
所有的冗余组件都以并行的方式对事件做出响应。仅使用一个组件的响应,丢弃其余组件的响应。错误发生时,使用该战术的系统的停机时间通常是几毫秒,因为备份是最新的,所以恢复所需要的时间就是切换时间。 - 被动冗余(暖重启/双冗余/三冗余)
一个组件对事件做出响应,并通知其他组件必须进行状态更新。当错误发生时,在继续提供服务前,系统必须首先确保备用状态是最新的。 - 备件
备用是计算平台配置用于更换各种不同的故障组件。出现故障时,必须将其重新启动为适当的软件配置,并对其状态进行初始化。 - shadow操作
以前出现故障组件可以在短时间内以"shadow模式"运行,以确保在恢复该组件之前,模仿工作组件的行为。 - 状态再同步
主动和被动冗余战术要求所恢复的组件在重新提供服务前更新其状态。更新方法取决于可以承受的停机时间、更新的规模以及更新所要求的消息的数量。如果可能的话,最好用一条消息包含该状态。增量式状态更新和两个增量之间的服务周期会导致复杂的软件。 - 检查点/回滚
检查点就是记录所创建一致状态,或者是定期进行,或者是对具体事件做出响应。有时系统会以一种不同寻常的方式出现故障,可检测到其状态不一致。在这种情况下,应该使用上一个一致检查点和拍了快照后所发生的事务的日志来恢复系统。
错误预防
- 从服务中删除
该战术从操作中删除了系统的一个组件,以执行某些活动来防止预期发生的故障。一个示例就是重新启动组件,以防止内存泄漏导致故障的发生。
这一点最常用的比如说在连接数据库,进行完操作之后,需要对连接组件进行关闭,防止重复开启发生故障。
package com.wang.util;
import java.sql.*;
public class DBUtil {
private static String driver;
private static String url;
private static String username;
private static String password;
static {
driver = "com.mysql.jdbc.Driver";
url = "jdbc:mysql://127.0.0.1:3306/wang?useSSL=false&characterEncoding=utf8";
username = "root";
password = "123456";
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConn() throws SQLException {
return DriverManager.getConnection(url, username, password);
}
public static void close(Connection conn, Statement st, ResultSet rs) {
try {
if (conn != null) {
conn.close();
}
if (st != null) {
st.close();
}
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
- 事务
事务就是绑定几个有序的步骤,以能够立刻撤销整个绑定。如果进程中的一个步骤失败的话,可以使用事务来防止任何数据受到影响,还可以使用事务来防止访问相同数据的几个同时线程之间发生冲突。 - 进程监视器
一旦检测到进程中存在错误,监视进程就可以删除非执行进程,并为该进程创建一个新的实例,就像在备件战术中一样,初始化为某个适当的状态。
总结
对于可用性战术的实例,按照之前我自己做的一些小项目来看,使用最多的便是登陆注册功能时所使用的信息填报时的检测。使用js函数对不符合要求的填报内容进行错误的抛出及提示。与此同时数据库的事务会进行回滚,回到事务未开始的状态。