解析:
导致系统不可用的原因有:
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?"成功":"失败")); }}
复制代码
评论