解析:
导致系统不可用的原因有:
1.硬件故障
2.软件 BUG
3.系统发布
4.并发压力
5.网络攻击
6.外部灾难
保障系统稳定高可用的方案有:
1.解耦:
1.1 组件设计原则(高内聚,低耦合)
1.1.1 组件内聚原则:复用发布等同原则,共同封闭原则,共同复用原则
1.1.2 组件耦合原则:无循环依赖原则,稳定依赖原则,稳定抽象原则
1.2 面向对象设计原则:
1.2.1 开放关闭原则(OCP)
1.2.2 依赖倒置原则(DIP)
1.2.3 里氏替换原则(LSP)
1.2.4 接口隔离原则(ISP)
1.2.5 单一职责原则(SRP)
1.3 面向对象设计模式
1.3.1 创建型:简单工厂,工厂方法(Factory method),
抽象工厂(Abstract Method),原型(Prototype),
建造者(Builder),享元(Flyweight),单例(Singleton)
1.3.2 结构型:组合模式(Composite),代理模式(Proxy),适配器(Adapter),
外观模式(Facade),桥接模式(Bradge),装饰着(Decorator)
1.3.3 行为型: 观察者(Observer),职责链(chain of Responsibility),
迭代器(Iterator),命令(command),策略(Strategy),
状态(State),模板(Template),解释器,中介者,
调停者,备忘录,访问者
2.隔离:
2.1 业务与子系统隔离
2.2 微服务与中台架构
2.3 生产者和消费者隔离
2.4 虚拟机与容器隔离
3.异步:
3.1 多线程编程
3.2 反应式编程
3.3 异步通信网络编程
3.4 事件驱动异步架构
4.备份:
4.1 集群设计
4.2 数据库复制
5.失效转移:
5.1 数据库主主失效转移
5.2 负载均衡失效转移
6.幂等:服务多次调用和一次调用效果相同。
7.事务补偿:业务逻辑逆向操作,使事务回滚到事务前状态。
8.重试:修复单次调用故障
9.熔断:断路器阻断对故障服务的调用。断路器三种状态:关闭,打开,半开。
10.限流
10.1 计数器算法(固定窗口,滑动窗口)
10.2 令牌桶算法
10.3 漏桶算法
11.降级
12.异地多活
解析:
package org.geekbang.training.arch;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
public class MD5Utils {
/**
* byte[]字节数组 转换成 十六进制字符串
* @param arr 要转换的byte[]字节数组
* @return String 返回十六进制字符串
*/
private static String hex(byte[] arr) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < arr.length; ++i) {
sb.append(Integer.toHexString((arr[i] & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString();
}
/**
* MD5加密,并把结果由字节数组转换成十六进制字符串
* @param str 要加密的内容
* @return String 返回加密后的十六进制字符串
*/
private static String md5Hex(String str) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(str.getBytes());
return hex(digest);
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.toString());
return "";
}
}
/**
* 生成含有随机盐的密码
* @param password 要加密的密码
* @return String 含有随机盐的密码
*/
public static String generate(String password) {
// 生成一个16位的随机数
Random random = new Random();
StringBuilder sBuilder = new StringBuilder(16);
sBuilder.append(random.nextInt(99999999)).append(random.nextInt(99999999));
int len = sBuilder.length();
if (len < 16) {
for (int i = 0; i < 16 - len; i++) {
sBuilder.append("0");
}
}
// 生成最终的加密盐
String salt = sBuilder.toString();
password = md5Hex(password + salt);
char[] cs = new char[48];
for (int i = 0; i < 48; i += 3) {
cs[i] = password.charAt(i / 3 * 2);
char c = salt.charAt(i / 3);
cs[i + 1] = c;
cs[i + 2] = password.charAt(i / 3 * 2 + 1);
}
return String.valueOf(cs);
}
/**
* 验证密码
* @param password 原密码
* @param password 加密之后的密码
*/
public static boolean verify(String password, String md5str) {
char[] cs1 = new char[32];
char[] cs2 = new char[16];
for (int i = 0; i < 48; i += 3) {
cs1[i / 3 * 2] = md5str.charAt(i);
cs1[i / 3 * 2 + 1] = md5str.charAt(i + 2);
cs2[i / 3] = md5str.charAt(i + 1);
}
String Salt = new String(cs2);
return md5Hex(password + Salt).equals(String.valueOf(cs1));
}
}
复制代码
package org.geekbang.training.arch.domain.model;
/**
* 领域模型:用户 User
* ***/
public interface User {
boolean checkPassword(String userId,String password);
boolean checkPassword(String userId,String password,String encryptedPassword);
}
复制代码
package org.geekbang.training.arch.domain.model;
import org.geekbang.training.arch.MD5Utils;
import org.geekbang.training.arch.UserEntity;
public class DefaultUser implements User {
private UserEntity userEntity;
public DefaultUser(UserEntity userEntity){
this.userEntity=userEntity;
}
@Override
public boolean checkPassword(String userId, String password) {
if(userId==null||
password==null||
this.userEntity==null||
!userId.equals(this.userEntity.getUserId()))
{
return false;
}
return checkPassword(userId,password,this.userEntity.getEncryptedPassword());
}
@Override
public boolean checkPassword(String userId, String password, String encryptedPassword) {
return MD5Utils.verify(password, encryptedPassword);
}
}
复制代码
package org.geekbang.training.arch;
public class UserEntity {
private String userId;
private String encryptedPassword;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getEncryptedPassword() {
return encryptedPassword;
}
public void setEncryptedPassword(String encryptedPassword) {
this.encryptedPassword = encryptedPassword;
}
}
复制代码
package org.geekbang.training.arch;
import org.geekbang.training.arch.domain.model.DefaultUser;
import org.geekbang.training.arch.domain.model.User;
public class UserTest {
public static void main(String[] args){
UserEntity userEntity=new UserEntity();
userEntity.setUserId("tomcat");
userEntity.setEncryptedPassword(MD5Utils.generate("123456"));
User user=new DefaultUser(userEntity);
boolean result = user.checkPassword("tomcat","123456");
System.out.println(("密码验证:")+(result?"成功":"失败"));
}
}
复制代码
评论