写点什么

「架构师训练营」作业:第 11 周

用户头像
Amy
关注
发布于: 2020 年 08 月 24 日

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

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



  • 硬件故障

我第一家公司是有自建机房的,遇到最多的硬件故障是硬盘故障。服务器过了使用期限没有更换,随时都有宕机的可能。



  • 软件 bug

业务逻辑的漏洞、软件设计的疏漏,都会导致软件 bug。严格的测试能够很大限度地降低软件的 bug 。



  • 系统发布

如果系统只能人肉发布的话,是不可能避免错误的。打包的时候打包错版本;发布的时候配置文件没有更新;数据表新增字段没有在发布之前执行脚本;只部分服务器更新了系统,部分没有更新,造成业务逻辑异常。这些都是在发布的时候经常出现的。一般在发布之后都要留意日志,看看数据,发现异常及时修正。



  • 并发压力

系统并发量突然增加很容易会导致服务器宕机,每年双十一、黑五这些大促节日,订单量都会激增,相关的服务是不能够停的,只能增加服务器,并且关掉一些不是很重要的服务。



  • 网络攻击

黑客利用系统漏洞或者DDOS攻击造成系统不可用。



  • 外部灾害

停电、光纤被挖断、雷劈等等自然灾害,会导致系统不可用。

每到夏天的雷雨天气,机房的线路必然会出现问题的,还会停电。这个时候整个系统都要停下来了。



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



  • 解耦

高内聚、低耦合的组件设计原则

  • 面向对象基本设计原则

  • 面向对象设计模式

  • 领域驱动设计建模

    • 隔离

    业务与子系统隔离

  • 微服务与中台架构

  • 生产者消费者隔离

  • 虚拟机与容器隔离

    • 异步

    多线程编程

  • 反应式编程

  • 异步通信网络编程

  • 事件驱动异步架构

    • 备份

    集群设计

  • 数据库复制

    • Failover(失效转移)

    数据库主主失效转移

  • 负载均衡失效转移

    • 幂等

    服务重复调用有时候是无法避免的,必须保证服务重复调用和调用一次产生的结果相同,即服务具有幂等性。

    • 事务补偿

    通过执行业务逻辑逆操作,使事务回滚到事务前状态。

    • 重试

    远程服务可能由于线程阻塞、垃圾回收或者网络抖动,而无法及时返回响应,调用者可以通过重试的方式修复单词调用的故障。

    上游调用者超时时间要大于下游调用者超时时间之和

    • 熔断

    当某个服务出现故障,响应延迟或者失败率增加,继续调用这个服务会导致调用者请求阻塞,资源消耗增加,进而出现服务级联失效,这种情况下使用断路器阻断对故障服务的调用

    断路器三种状态:关闭、打开、半开

    Spring Cloud 断路器实现:Hystrix

    • 限流

    在高并发场景下,如果系统的访问量超过了系统的承受能力,可以通过限流对系统进行保护。

    限流的算法:计数器算法、令牌桶算法、漏桶算法

    自适应限流:

    没有提前的人工评估,便没有提前的评估过时与人的评估疏漏/错误

    实时自动评估 QPS

    业务流量的不确定性与技术方案的自适应行天生一对。

    • 降级

    在系统高并发的时候,一些非核心功能关闭。

    • 异地多活

    将数据中心分布在多个不同地点的机房里,这些机房都可以对外提供服务,用户可以连接任何一个机房进行访问。每个机房都可以提供完整的系统服务,即使某一个机房不可用,系统也不会宕机,亦然保持可用。

    难点是数据一致

    

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

    

    语言:C#

    IDE:Visual Studio 2019

    Sdk:.net core 3.1

    

    工具类:

    public class MyPwdCheck
    {
    private readonly string _Salt = "Hello World";
    /// <summary>
    /// 用户密码验证
    /// </summary>
    /// <param name="userId">用户 Id</param>
    /// <param name="password">密码明文</param>
    /// <param name="passwordEncryption">密码密文</param>
    /// <returns></returns>
    public bool checkPW(string userId,string password,string passwordEncryption)
    {
    if(string.IsNullOrWhiteSpace(userId)
    || string.IsNullOrWhiteSpace(password)
    || string.IsNullOrWhiteSpace(passwordEncryption))
    return false;
    return passwordEncryption.Equals(EncryptMd5($"{userId}{_Salt}{password}"));
    }
    /// <summary>
    /// md5 加密
    /// </summary>
    /// <param name="source"></param>
    /// <returns></returns>
    private string EncryptMd5(string source)
    {
    MD5 md5 = new MD5CryptoServiceProvider();
    byte[] targetData = md5.ComputeHash(Encoding.UTF8.GetBytes(source));
    var sb = new StringBuilder();
    for(int i = 0; i < targetData.Length; i++)
    {
    sb.Append(targetData[i].ToString("x2"));
    }
    return sb.ToString();
    }
    }

    测试:

    class Program
    {
    static void Main(string[] args)
    {
    try
    {
    string userId = "10086";
    string password = "Amy Lo";
    Console.WriteLine($"userId : {userId}");
    Console.WriteLine($"password : {password}");
    string passwordEncryption = "4be098269e6e7b60966cae74fc1cb1aa";
    Console.WriteLine($"passwordEncryption : {passwordEncryption}");
    var check = new MyPwdCheck();
    Console.WriteLine();
    Console.WriteLine($"结果:{check.checkPW(userId,password,passwordEncryption)}");
    }
    catch(Exception ex)
    {
    Console.WriteLine(ex.ToString());
    }
    Console.ReadLine();
    }
    }

    结果:

    

    用户头像

    Amy

    关注

    还未添加个人签名 2018.06.10 加入

    还未添加个人简介

    评论

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