写点什么

架构师训练营第 2 期 第 11 周命题作业

用户头像
月下独酌
关注
发布于: 2021 年 01 月 03 日

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


系统不可用的原因

硬件故障,主服务所在机器宕机等。

软件 BUG,如代码层面的编写问题。

系统发布,如发布过程错误处理了分支在合并时的冲突。

并发压力,请求访问量超过了系统服务,数据库服务的承载能力,导致系统假死。

网络攻击,比如大量请求,XSS 攻击等。

外部灾害,比如地震,断电,工程队挖断了光缆等。


保障系统稳定高可用的方案

1、解耦

2、隔离

隔离首先依赖于解耦,按业务层面上划分,在物理层面上(部署在不同的服务器)实现隔离

具体有

(1)业务与子系统隔离:部分子系统的崩溃不能去影响到其他不相关的功能。

(2)微服务与中台架构:子系统更细粒度的拆分,且能做集群,能容灾备份,即使挂了部分微服务,不影响服务的整体可用,不影响到用户。

(3)生成者与消费者隔离:生产者与消费者部署在不同的服务器上,使用分布式消息队列(隔离开),如果一方出现故障不会影响到另一方。

(4)虚拟机与容器隔离:不同的业务可部署在不同的虚拟机里,如果某个虚拟机内的进程抛出了会停止运行的 BUG(比如 OOM),则不会影响其他虚拟机上的业务,容器同理。



3、异步

多线程编程:单一线程的故障不影响其他线程,也是把故障隔离开

反应式编程:依赖异步消息传递机制,组件解耦,故障单独处理。

异步通信网络编程:避免网络阻塞降低网络可用性

事件驱动异步架构:利用了消息队列达成生成者与消费者隔离的效果。



4、备份

集群设计:多台服务器,用来应对部分服务器宕机的场景

数据库复制:应付数据库压力过大,以及数据库服务器宕机等场景,

失效转移:当系统监控到某台服务器宕机,要把前往该服务器的请求,转移到其他服务器上。



5、幂等

因网络波动、调用、失效转移等会出现操作命令重发的场景,要小心考虑是否需要进行幂等性处理。



6、事务补偿

在单台服务器以及单台数据库服务器的操作时,如出现问题,通过传统事务回滚到事务前的状态。

在分布式环境下,可能业务操作在不同的服务器,不同的数据库连接,甚至不同的数据库,分布式事务有时候过于繁重,此时需要依赖业务逻辑上的逆操作,来补偿。



7、重试

当出现长时间未收到请求时,上级调用者可能需要重新调用。同时,上级的超时时间要大于下级操作时间之和。



8、熔断

服务(上某个方法)出现故障到一定程度,如单位时间内出错达到 50%,宣告该服务不可用,熔断器打开,调用该方法上的熔断方法去执行。过段时间尝试发送请求,判断是否维持熔断器开关打开状态。



9、限流

系统访问量超过系统承受能力,需要对请求进行限制,即需要抛弃部分用户请求,影响部分用户的使用。限流的方法:计数器算法(固定窗口、滑动窗口)、令牌桶算法,漏桶算法。


10、降级

非核心的功能可能有承担较大的压力,当整体系统压力上来时,可以把这些功能占用的资源让给其他功能。



11、异地多活

因自然灾害或生产事故等不可抗力导致的不可用,异地进行系统备份。


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


  public final static String MD5(String s) {        char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};        try {            byte[] btInput = s.getBytes();            MessageDigest mdInst = MessageDigest.getInstance("MD5");            // 使用指定的字节更新摘要            mdInst.update(btInput);            // 获得密文            byte[] md = mdInst.digest();            // 把密文转换成十六进制的字符串形式            int j = md.length;            char str[] = new char[j * 2];            int k = 0;            for (int i = 0; i < j; i++) {                byte byte0 = md[i];                str[k++] = hexDigits[byte0 >>> 4 & 0xf];                str[k++] = hexDigits[byte0 & 0xf];            }            return new String(str);        } catch (Exception e) {            e.printStackTrace();            return "";        }    }


public static final String salt = "ceshi_20200103";
public static boolean checkPW(String id,String password,String md5pwd){ boolean result = false; if(!"".equals(password) && !"".equals(md5pwd)){ result = md5pwd.equals(MD5(password + salt)); } return result; }
复制代码


用户头像

月下独酌

关注

还未添加个人签名 2019.07.22 加入

还未添加个人简介

评论

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