架构师训练营第十一周课后作业

用户头像
Gosling
关注
发布于: 2020 年 12 月 06 日

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

导致系统有很多原因,具体大致可以分为:系统资源问题,代码Bug问题,网络延迟问题,发布环境问题,各类外部因素问题。

导致故障的各类原因

系统资源问题

大部分的一些故障的直接表现就是服务器系统资源不够用,CPU、内存、磁盘I/O等达到了上限,这里我们先不考虑其他原因,姑且只算是纯粹的硬件资源不够用,当用户访问了增加或是在某个高峰期集中访问时,表现出来的现象就是服务器无法处理大量的请求甚至是整个JVM就崩溃退出。

代码Bug问题

代码Bug也是一种常见的导致系统不可用的问题,例如从数据库查询出来的数据没有做非空判断,一旦为空,可能会导致NPE异常,这类Bug有的时候很难在开发或测试阶段被发现,所以一些通常的代码规范需要做好。

网络延迟问题

当我们的架构是一些微服务架构时,网络波动或一些主干网出现问题时,整体表现就是系统的请求大量超时,在用户的角度来看,这个系统就是不可用的。

发布环境问题

环境问题属于一些人为错误,例如在生产环境数据库应该有的字段没有及时添加,一些内部调试的代码没有及时修改被合并到上线发布分支,访问的环境变量参数等忘记修改导致一些服务无法正常访问,这些问题通常是由于在发布环节依赖人工处理,当发布过程复杂时难免会出现遗漏,导致线上服务不可用。

各类外部因素问题

除了我们内部的问题,还有各类外部因素,例如机房的机器出现故障、机房失火、网络传输光缆损坏甚至是数据中心发生自然灾害等,这类我们无法控制的异常突发事件也会导致我们系统服务器无法对外正常提供服务。

保证系统高可用的方案

要做好系统高可用,关键把握住以下几点:

合理的可扩展方案和冗余资源

应对高并发和海量存储的场景,当系统资源无法支持时,我们如果需要承受这样的请求,那么唯一的办法就是提升硬件性能和做水平的负载扩展,我们需要有一些应对外部请求变化灵活伸缩的方案,保证忙时和闲时可以自由调整管理系统的服务集群。

同时,我们对核心服务乃至全部服务都做一套备用,当出现硬件故障问题时,我们可以用备用的服务器保证的系统依然可以对外正常提供服务,这里的备份还要充分考虑到突发事件,例如火灾、地震甚至是战争。需要把备用服务的机器部署在同城其他机房甚至是异地做一些灾备。

可以说在系统资源上下功夫做高可用投入的成本是巨大的,除了一线的头部的互联网公司,大部分的公司都要考虑自己的投资回报率,合理评估自己在这个手段中应该做到什么程度,5个9的SLA挑战是非常巨大的。

管理流程规范化

除了一些硬性的硬件投入之外,很大一部分原因是人为因素导致的问题,那就需要从我们的管理手段上去解决。

我们需要有一套合理的代码版本管理机制,保证我们的发布代码是可靠的,我们可以加入自动化脚本减少人工去判断代码问题的工作量,对于核心模块需要加入人工审核做代码Review,增加可靠性,一些系统配置项交给一些发布框架去集成,减少手工修改导致的错误。

建立良好的代码规约,减少因为代码编写低质量导致的各类系统故障问题。

在发布过程建立一套良好的预验证机制,先小规模发布一部分机器,在线上环境做一些验证,验证通过后再逐步分发到其他机器进行版本升级。

2.单向散列算法

请用你熟悉的编程语言写一个用户密码验证函数,Boolean checkPW(String 用户 ID,String 密码明文,String 密码密文),返回密码是否正确 boolean 值,密码加密算法使用你认为合适的加密算法。
public Boolean checkPW(String userId, String inputPassword, String dbPassword) throws UnsupportedEncodingException, NoSuchAlgorithmException{
inputPassword = inputPassword + getSalt(inputPassword);
MessageDigest md5 = MessageDigest.getInstance("MD5");
StringBuilder result = new StringBuilder("");
byte[] bytes = md5.digest(inputPassword.getBytes("UTF-8"));
for (byte b : bytes) {
String temp = Integer.toHexString(b & 0xff);
if (temp.length() == 1) {
temp = "0" + temp;
}
result.append(temp);
}
String hashPassword = result.toString();
return hashPassword.equals(dbPassword);
}
private String getSalt(String inputPassword) {
//此处简化根据一些内容提取盐的过程,假设密码不小于6位,可以用更复杂的方式构造盐,目的是让MD5查表失效
if(inputPassword.length() < 6) {
throw new RuntimeException("密码长度必须大于等于6位");
}
return inputPassword.substring(5);
}



用户头像

Gosling

关注

这个家伙很懒,只留下这一句话 2017.10.28 加入

还未添加个人简介

评论

发布
暂无评论
架构师训练营第十一周课后作业