写点什么

架构师训练营第 11 周作业

用户头像
关注
发布于: 2020 年 08 月 26 日
架构师训练营第 11 周作业

先给交作业这么晚来个理由:最近实在是太忙了。从上周开始忙着职级调整答辩(太费劲了,写个PPT写了10个小时),周末还做容灾演练,又在学习Flink,学投资,另外项目进度也落后了。所有的事都感觉很重要,加上时间安排的与实际完全不一致(答辩和写PPT花了太长的时间)。

项目进度落后了,必须靠加班来往回赶啦!!!

1. 导致系统不可用的原因有哪些?保障系统稳定高可用的方案有哪些?请分别列举并简述。

1.1 导致系统不可用的原因有哪些?

  • 网络不可达(系统服务相关网络配置、物理线路断了等)

  • 系统服务宕掉(内存溢出挂了、硬件资源坏了、还单点)

  • 缓存使用不当,导致流量分配不均,缓存击穿,所有服务被逐个击破

  • 资源未释放,导致请求都在等待获取资源,卡死了

  • 有人删库跑路了

  • DDOS攻击导致带宽被占满,正常请求也无法正常接入

  • 系统发布问题(发布步骤不对导致系统无法正常启动,配置文件用错无法连接相关资源等)

  • 访问受限(例如:公司网络防火墙限制、国安限制国外网络服务等)

  • 有时候服务是可用,可是提供的服务产生错误

下来看看老师总结的几点吧:

  • 硬件故障

  • 软件Bug

  • 系统发布

  • 并发压力

  • 网络攻击

  • 外部灾害

1.2 保障系统稳定高可用的方案有哪些?

  • 拒绝单点,首先保证服务存在多点,最好能够异地多活

  • 合理使用缓存,有效降低核心系统资源压力

  • 编码规范,不要开发一些已知的低级漏洞的代码,例如SQL注入

  • 做好安全防护,及时修复漏洞,防止外部攻击

  • 采用良好的设计,系统功能独立部署,降低所有服务均无法提供服务的情形

  • 降级处理,压力特别大的时候采用释放非核心功能资源,保障核心功能稳定服务

  • 采用限流措施,保证系统服务能力稳定

  • 发布时可以采用逐步发布的方式,出现问题可将影响控制在可控范围之内

  • 根据不同的服务能力采用合适的资源:带宽、CPU、内存、存储等

下来看看老师总结的几点吧:

系统架构和开发层面:

  • 采用良好的设计原则和建模方法对系统服务进行解耦

  • 隔离:业务与子系统、微服务与中台、虚拟机与容器、生产者与消费者等

  • 采用异步方式,提升系统处理能力

  • 冗余备份,失效转移

  • 采用幂等、事务补偿、重试等方式保证业务的正确性与完整性

  • 在服务出现故障时采用熔断机制可以保障正常系统的服务能力

  • 通过限流,使系统服务在可承受的压力下提供稳定的服务

  • 采用降级,保障核心服务能力

  • 异地多活(难点在于保持数据的一致性)

系统运维层面:

  • 发布运维有合理的流程

  • 测试、部署自动化可以降低人工处理出错的风险

  • 良好的代码版本管理可以保证运维发布版本的准确性

  • 采用灰度发布,先小范围发布,使风险控制在可控范围之内

  • 全面的系统监控,及时发现风险,提前做好风险应对预案

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

为了能够更好地解释登录验证地过程,在作业的代码实现中模拟了用户注册、用户登录的过程,为了简单起见,都用了静态方法来实现,整个代码包含以下几个方面:

1. 密码加密算法:此处我采用了SHA-1算法

2. 模拟用户注册

3. 模拟用户登录

2.1用户密码加密算法实现

private static String toString(MessageDigest digest) {
String sha1 = new BigInteger(1, digest.digest()).toString(16);
int length = 40 - sha1.length();
if (length > 0) {
for (int i = 0; i < length; i++) {
sha1 = "0" + sha1;
}
}
return sha1;
}
public static String encode(String str, String type) {
if (str == null) {
return null;
}
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
if (type != null) {
String header = type + " " + str.getBytes().length + "\0";
messageDigest.update(header.getBytes());
}
messageDigest.update(str.getBytes());
return toString(messageDigest);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

2.2 用户注册实现

private static Map<String, String> userStore = new ConcurrentHashMap<>();
/**
* 模拟注册
*
* @param userId
* @param password
*/
public static void regist(String userId, String password) {
userStore.put(userId, encode(password, userId));
}

2.3 用户登录实现

/**
* 密码校验
*
* @param userId
* @param plainPassword
* @return
*/
public static boolean checkPassword(String userId, String plainPassword, String secretPassword) {
if (userId == null || plainPassword == null || secretPassword == null) {
return false;
}
return secretPassword.equalsIgnoreCase(encode(plainPassword, userId));
}
/**
* 模拟登录
*
* @param userId
* @param password
*/
public static boolean login(String userId, String password) {
// 模拟从获取用户密码密文信息
String secretPassword = userStore.get(userId);
if (secretPassword == null) {
System.out.println(String.format("日志:账号【%s】不存在!", userId));
return false;
}
boolean loginResult = checkPassword(userId, password, secretPassword);
if (loginResult) {
System.out.println(String.format("日志:账号【%s】登录成功!", userId));
} else {
System.out.println(String.format("日志:账号【%s】密码不正确!", userId));
}
return loginResult;
}

2.4 模拟用户注册与登录测试


public static void main(String[] args) {
// 注册
String userId = "CrazyGeek";
String password = "GeekIsNo1!";
regist(userId, password);

// 模拟登录
String loginUserId = "CrazyGeek";
String loginPassword = "GeekIsNo1!";
boolean loginResult = login(loginUserId, loginPassword);
if (loginResult) {
System.out.println("跳转到个人页面!");
} else {
System.out.println("提示:账号或密码错误!");
}
}

2.4.1 模拟登录结果

能发现登录失败的原因吗?

2.4.2 登录成功的打印结果

2.4.3 账号不存在的打印结果



用户头像

关注

懒是一种艺术 2018.03.26 加入

间歇性自律,持续性懒散,真的很懒!

评论

发布
暂无评论
架构师训练营第 11 周作业