写点什么

11.8 作业

用户头像
张荣召
关注
发布于: 2020 年 12 月 06 日
  • 导致系统不可用的原因有哪些?保障系统稳定高可用的方案有哪些?请分别列举并简述

  解析:

           导致系统不可用的原因有:

           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.异地多活

  • 请用你熟悉的编程语言写一个用户密码验证函数,Boolean checkPW(String 用户 ID,String 密码明文,String 密码密文),返回密码是否正确 boolean 值,密码加密算法使用你认为合适的加密算法。

解析:

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?"成功":"失败")); }}

复制代码


用户头像

张荣召

关注

还未添加个人签名 2018.05.02 加入

还未添加个人简介

评论

发布
暂无评论
11.8作业