个人网站做企业备案,广告设计公司需要用专线网吗,外部调用wordpress站点文章,网站的页面【后端开发】服务开发场景之高可用#xff08;冗余设计#xff0c;服务限流#xff0c;降级熔断#xff0c;超时重试#xff0c;性能测试#xff09; 文章目录 序#xff1a;如何设计一个高可用的系统#xff1f;可用性的判断指标是什么#xff1f;哪些情况会导致系统…【后端开发】服务开发场景之高可用冗余设计服务限流降级熔断超时重试性能测试 文章目录 序如何设计一个高可用的系统可用性的判断指标是什么哪些情况会导致系统不可用有哪些提高系统可用性的方法 1、未雨绸缪冗余设计2、东窗事发服务的限流、降级、熔断服务限流请求速率服务降级整体功能服务熔断下游故障 3、事后补救超时重试性能测试超时重试性能测试 附参考资料 序如何设计一个高可用的系统
可用性的判断指标是什么
高可用描述的是一个系统在大部分时间都是可用的可以为我们提供服务的。高可用代表系统即使在发生硬件故障或者系统升级的时候服务仍然是可用的。 一般情况下我们使用多少个 9 来评判一个系统的可用性比如 99.9999% 就是代表该系统在所有的运行时间中只有 0.0001% 的时间是不可用的这样的系统就是非常非常高可用的了当然也会有系统如果可用性不太好的话可能连 9 都上不了。 除此之外系统的可用性还可以用某功能的失败次数与总的请求次数之比来衡量比如对网站请求 1000 次其中有 10 次请求失败那么可用性就是 99%。 什么是“5个9”的可靠性, 3个9(1-99.9%)365248.76小时表示该系统在连续运行1年时间里最多可能的业务中断时间是8.76小时。 4个9(1-99.99%)365240.876小时52.6分钟表示该系统在连续运行1年时间里最多可能的业务中断时间是52.6分钟。 5个9(1-99.999%)36524*605.26分钟表示该系统在连续运行1年时间里最多可能的业务中断时间是5.26分钟。 【MTBF】MTBF,即平均故障间隔时间英文全称是“Mean Time Between Failure”。是衡量一个产品尤其是电器产品的可靠性指标。单位为“小时”。具体来说是指相邻两次故障之间的平均工作时间也称为平均故障间隔。 【失效率】失效率是指工作到某一时刻尚未失效的产品在该时刻后单位时间内发生失效的概率。一般记为λ它也是时间t的函数故也记为λ(t)称为失效率函数有时也称为故障率函数或风险函数。 【MTTR】MTTR全称是Mean Time To Repair即平均修复时间。是指可修复产品的平均修复时间就是从出现故障到修复中间的这段时间。MTTR越短表示易恢复性越好。 【修复率】修复率(μ) repair rate 产品维修性的一种基本参数。修理时间已达到某个时刻但尚未修复的产品在该时刻后的单位时间内完成修理的概率。
哪些情况会导致系统不可用
黑客攻击硬件故障比如服务器坏掉。并发量/用户请求量激增导致整个服务宕掉或者部分服务不可用。代码中的坏味道导致内存泄漏或者其他问题导致程序挂掉。网站架构某个重要的角色比如 Nginx 或者数据库突然不可用。自然灾害或者人为破坏。
有哪些提高系统可用性的方法 注重代码质量测试严格把关 代码质量有问题比如比较常见的内存泄漏、循环依赖都是对系统可用性极大的损害。比较实际可用的就是 CodeReview。 使用集群减少单点故障 如何保证我们的 Redis 缓存高可用呢答案就是使用集群避免单点故障。 限流 流量控制flow control其原理是监控应用流量的 QPS 或并发线程数等指标当达到指定的阈值时对流量进行控制以避免被瞬时的流量高峰冲垮从而保障应用的高可用性 超时和重试机制设置 一旦用户请求超过某个时间的得不到响应就抛出异常。 这个是非常重要的很多线上系统故障都是因为没有进行超时设置或者超时设置的方式不对导致的。我们在读取第三方服务的时候尤其适合设置超时和重试机制。 一般我们使用一些 RPC 框架的时候这些框架都自带的超时重试的配置。如果不进行超时设置可能会导致请求响应速度慢甚至导致请求堆积进而让系统无法再处理请求。 重试的次数一般设为 3 次再多次的重试没有好处反而会加重服务器压力部分场景使用失败重试机制会不太适合。 熔断机制 熔断机制说的是系统自动收集所依赖服务的资源使用情况和性能指标当所依赖的服务恶化或者调用失败次数达到某个阈值的时候就迅速失败让当前系统立即切换依赖其他备用服务。 比较常用的流量控制和熔断降级框架是 Netflix 的 Hystrix 和 alibaba 的 Sentinel。 异步调用 异步调用的话我们不需要关心最后的结果这样我们就可以用户请求完成之后就立即返回结果具体处理我们可以后续再做秒杀场景用这个还是蛮多的。 使用缓存 如果我们的系统属于并发量比较高的话如果我们单纯使用数据库的话当大量请求直接落到数据库可能数据库就会直接挂掉。使用缓存缓存热点数据因为缓存存储在内存中所以速度相当地快
更多
核心应用和服务优先使用更好的硬件监控系统资源使用情况增加报警设置。注意备份必要时候回滚。灰度发布 将服务器集群分成若干部分每天只发布一部分机器观察运行稳定没有故障第二天继续发布一部分机器持续几天才把整个集群全部发布完毕期间如果发现问题只需要回滚已发布的一部分服务器即可定期检查/更换硬件 如果不是购买的云服务的话定期还是需要对硬件进行一波检查的对于一些需要更换或者升级的硬件要及时更换或者升级。
1、未雨绸缪冗余设计
冗余设计是保证系统和数据高可用的最常的手段。
对于服务来说冗余的思想就是相同的服务部署多份如果正在使用的服务突然挂掉的话系统可以很快切换到备份服务上大大减少系统的不可用时间提高系统的可用性。对于数据来说冗余的思想就是相同的数据备份多份这样就可以很简单地提高数据的安全性。实际上日常生活中就有非常多的冗余思想的应用。我对于重要文件的保存方法就是冗余思想的应用GitHub个人云盘。
高可用集群High Availability Cluster简称 HA Cluster、同城灾备、异地灾备、同城多活和异地多活是冗余思想在高可用系统设计中最典型的应用。
高可用集群 : 同一份服务部署两份或者多份当正在使用的服务突然挂掉的话可以切换到另外一台服务从而保证服务的高可用。同城灾备一整个集群可以部署在同一个机房而同城灾备中相同服务部署在同一个城市的不同机房中。并且备用服务不处理请求。这样可以避免机房出现意外情况比如停电、火灾。异地灾备类似于同城灾备不同的是相同服务部署在异地通常距离较远甚至是在不同的城市或者国家的不同机房中同城多活类似于同城灾备但备用服务可以处理请求这样可以充分利用系统资源提高系统的并发。异地多活 : 将服务部署在异地的不同机房中并且它们可以同时对外提供服务。
特点
高可用集群单纯是服务的冗余并没有强调地域。同城灾备、异地灾备、同城多活和异地多活实现了地域上的冗余。和传统的灾备设计相比同城多活和异地多活最明显的改变在于“多活”即所有站点都是同时在对外提供服务的。异地多活是为了应对突发状况比如火灾、地震等自然或者人为灾害。光做好冗余还不够必须要配合上 故障转移 才可以 所谓故障转移简单来说就是实现不可用服务快速且自动地切换到可用服务整个过程不需要人为干涉。举个例子哨兵模式的 Redis 集群中如果 Sentinel哨兵 检测到 master 节点出现故障的话 它就会帮助我们实现故障转移自动将某一台 slave 升级为 master确保整个 Redis 系统的可用性。 整个过程完全自动不需要人工介入。再举个例子Nginx 可以结合 Keepalived 来实现高可用。如果 Nginx 主服务器宕机的话Keepalived 可以自动进行故障转移备用 Nginx 主服务器升级为主服务。并且这个切换对外是透明的因为使用的虚拟 IP虚拟 IP 不会改变。
2、东窗事发服务的限流、降级、熔断
服务限流请求速率
服务限流是什么
针对软件系统来说限流就是对请求的速率进行限制避免瞬时的大量请求击垮软件系统。限流可能会导致用户的请求无法被正确处理或者无法立即被处理不过这往往也是权衡了软件系统的稳定性之后得到的最优解。
常见限流算法有哪些
1、固定窗口计数器算法 固定窗口其实就是时间窗口其原理是将时间划分为固定大小的窗口在每个窗口内限制请求的数量或速率即固定窗口计数器算法规定了系统单位时间处理的请求数量。 优点实现简单易于理解。 缺点限流不够平滑。例如我们限制某个接口每分钟只能访问 30 次假设前 30 秒就有 30 个请求到达的话那后续 30 秒将无法处理请求这是不可取的用户体验极差2、滑动窗口计数器算法 固定窗口计数器算法的升级版限流的颗粒度更小。优化在于它把时间以一定比例分片 。我们可以把 1 分钟分为 60 个窗口。每隔 1 秒移动一次。当滑动窗口的格子划分的越多滑动窗口的滚动就越平滑限流的统计就会越精确。 缺点与固定窗口计数器算法类似滑动窗口计数器算法依然存在限流不够平滑的问题。3、漏桶算法 我们可以把发请求的动作比作成注水到桶中我们处理请求的过程可以比喻为漏桶漏水。我们往桶中以任意速率流入水以一定速率流出水。当水超过桶流量则丢弃因为桶容量是不变的保证了整体的速率。 准备一个队列用来保存请求然后我们定期从队列中拿请求来执行就好了和消息队列削峰/限流的思想是一样的 缺点无法应对突然激增的流量因为只能以固定的速率处理请求对系统资源利用不够友好。实际业务场景中基本不会使用漏桶算法。4、令牌桶算法 我们的主角还是桶不过现在桶里装的是令牌了请求在被处理之前需要拿到一个令牌请求处理完毕之后将这个令牌丢弃删除。我们根据限流大小按照一定的速率往桶里添加令牌。如果桶装满了就不能继续往里面继续添加令牌了。 缺点如果令牌产生速率和桶的容量设置不合理可能会出现问题比如大量的请求被丢弃、系统过载。
如何做服务限流 针对什么来进行限流 IP 针对 IP 进行限流适用面较广简单粗暴。 业务 ID挑选唯一的业务 ID 以实现更针对性地限流。例如基于用户 ID 进行限流。 个性化根据用户的属性或行为进行不同的限流策略。例如 VIP 用户不限流而普通用户限流。根据系统的运行指标如 QPS、并发调用数、系统负载等动态调整限流策略。例如当系统负载较高的时候控制每秒通过的请求减少。 单机限流怎么做 单机限流可以直接使用 Google Guava 自带的限流工具类 RateLimiter 。 RateLimiter 基于令牌桶算法可以应对突发流量。 分布式限流怎么做 针对的分布式/微服务应用架构应用常见的方案 借助中间件限流可以借助 Sentinel 或者使用 Redis 来自己实现对应的限流逻辑。 网关层限流比较常用的一种方案直接在网关层把限流给安排上了。不过通常网关层限流通常也需要借助到中间件/框架。就比如 Spring Cloud Gateway 的分布式限流实现RedisRateLimiter就是基于 RedisLua 来实现的再比如 Spring Cloud Gateway 还可以整合 Sentinel 来做限流。
服务降级整体功能
怎么做服务降级 引用
延迟服务比如发表了评论重要服务比如在文章中显示正常但是延迟给用户增加积分只是放到一个缓存中等服务平稳之后再执行。在粒度范围内关闭服务片段降级或服务功能降级比如关闭相关文章的推荐直接关闭推荐区页面异步请求降级比如商品详情页上有推荐信息/配送至等异步加载的请求如果这些信息响应慢或者后端服务有问题可以进行降级页面跳转页面降级比如可以有相关文章推荐但是更多的页面则直接跳转到某一个地址写降级比如秒杀抢购我们可以只进行Cache的更新然后异步同步扣减库存到DB保证最终一致性即可此时可以将DB降级为Cache。读降级比如多级缓存模式如果后端服务有问题可以降级为只读缓存这种方式适用于对读一致性要求不高的场景。
服务熔断下游故障
怎么做服务熔断 服务雪崩 多个微服务之间调用的时候假设微服务A调用微服务B和微服务C微服务B和微服务C有调用其他的微服务如果整个链路上某个微服务的调用响应式过长或者不可用对微服务A的调用就会占用越来越多的系统资源进而引起系统雪崩所谓的”雪崩效应” 断路器 “断路器”本身是一种开关装置当某个服务单元发生故障监控(类似熔断保险丝)向调用方法返回一个符合预期的、可处理的备选响应(FallBack)而不是长时间的等待或者抛出调用方法无法处理的异常这样就保证了服务调用方的线程不会被长时间、不必要地占用从而避免了故障在分布式系统中的蔓延。乃至雪崩。 服务熔断 熔断机制是应对雪崩效应的一种微服务链路保护机制当整个链路的某个微服务不可用或者响应时间太长时会进行服务的降级进而熔断该节点微服务的调用快速返回”错误”的响应信息。 Hystrix Hystrix是一个用于分布式系统的延迟和容错的开源库。在分布式系统里许多依赖不可避免的调用失败比如超时、异常等Hystrix能够保证在一个依赖出问题的情况下不会导致整个服务失败避免级联故障以提高分布式系统的弹性。
基本的断路器Curcuit Breaker结构如下 close状态下 client向supplier发起的服务请求 直接无阻碍通过断路器 supplier的返回值接直接由断路器交回给client. open状态下client向supplier发起的服务请求后断路器不会将请求转到supplier, 而是直接返回client, client和supplier之间的通路是断的 扩展的断路器模式 基本的断路器模式下保证了断路器在open状态时保护supplier不会被调用 但我们还需要额外的措施可以在supplier恢复服务后可以重置断路器。一种可行的办法是断路器定期探测supplier的服务是否恢复 一但恢复 就将状态设置成close。断路器进行重试时的状态为半开half-open状态。
服务熔断与服务降级比较
服务熔断一般是某个服务下游服务故障引起而服务降级一般是从整体负荷考虑。共性 目的 - 都是从可用性、可靠性出发提高系统的容错能力。最终表现-使某一些应用不可达或不可用来保证整体系统稳定。粒度 - 一般都是服务级别但也有细粒度的层面如做到数据持久层、只许查询不许增删改等。自治 - 对其自治性要求很高。都要求具有较高的自动处理机制。 区别 触发原因 - 服务熔断通常是下级服务故障引起服务降级通常为整体系统而考虑。管理目标 - 熔断是每个微服务都需要的是一个框架级的处理而服务降级一般是关注业务对业务进行考虑抓住业务的层级从而决定在哪一层上进行处理比如在IO层业务逻辑层还是在外围进行处理。实现方式 - 代码实现中的差异。
3、事后补救超时重试性能测试
超时重试
超时重试存在的意义
由于网络问题、系统或者服务内部的 Bug、服务器宕机、操作系统崩溃等问题的不确定性我们的系统或者服务永远不可能保证时刻都是可用的状态。为了最大限度的减小系统或者服务出现故障之后带来的影响我们需要用到的 超时Timeout 和 重试Retry 机制。对于微服务系统来说正确设置超时和重试非常重要。单体服务通常只涉及数据库、缓存、第三方 API、中间件等的网络调用而微服务系统内部各个服务之间还存在着网络调用。
什么是超时机制 超时机制说的是当一个请求超过指定的时间比如 1s还没有被处理的话这个请求就会直接被取消并抛出指定的异常或者错误比如 504 Gateway Timeout。 平常的两种超时 连接超时ConnectTimeout客户端与服务端建立连接的最长等待时间。 读取超时ReadTimeout客户端和服务端已经建立连接客户端等待服务端处理完请求的最长时间。实际项目中我们关注比较多的还是读取超时。 一些连接池客户端框架中可能还会有获取连接超时和空闲连接清理超时。 如果没有设置超时的话就可能会导致服务端连接数爆炸和大量请求堆积的问题。 整个网站无法正常处理请求服务器负载直接快被拉满。后面发现原因是项目超时设置错误加上客户端请求处理异常导致服务端连接数直接接近 40w这么多堆积的连接直接把系统干趴了。
超时时间应该如何设置
超时到底设置多长时间是一个难题超时值设置太高或者太低都有风险。 如果设置太高的话会降低超时机制的有效性比如你设置超时为 10s 的话那设置超时就没啥意义了系统依然可能会出现大量慢请求堆积的问题。 如果设置太低的话就可能会导致在系统或者服务在某些处理请求速度变慢的情况下比如请求突然增多大量请求重试超时通常会结合重试继续加重系统或者服务的压力进而导致整个系统或者服务被拖垮的问题。通常情况下我们建议读取超时设置为 1500ms ,这是一个比较普适的值。
什么是重试机制
重试机制一般配合超时机制一起使用指的是多次发送相同的请求来避免瞬态故障和偶然性故障。 瞬态故障可以简单理解为某一瞬间系统偶然出现的故障并不会持久。偶然性故障可以理解为哪些在某些情况下偶尔出现的故障频率通常较低。 重试的核心思想是通过消耗服务器的资源来尽可能获得请求更大概率被成功处理。 由于瞬态故障和偶然性故障是很少发生的因此重试对于服务器的资源消耗几乎是可以被忽略的。
常见的重试策略有哪些
固定间隔时间重试 每次重试之间都使用相同的时间间隔比如每隔 1.5 秒进行一次重试。这种重试策略的优点是实现起来比较简单不需要考虑重试次数和时间的关系也不需要维护额外的状态信息。但是这种重试策略的缺点是可能会导致重试过于频繁或过于稀疏从而影响系统的性能和效率。如果重试间隔太短可能会对目标系统造成过大的压力导致雪崩效应如果重试间隔太长可能会导致用户等待时间过长影响用户体验。梯度间隔重试 根据重试次数的增加去延长下次重试时间比如第一次重试间隔为 1 秒第二次为 2 秒第三次为 4 秒以此类推。这种重试策略的优点是能够有效提高重试成功的几率随着重试次数增加但是重试依然不成功说明目标系统恢复时间比较长因此可以根据重试次数延长下次重试时间也能通过柔性化的重试避免对下游系统造成更大压力。但是这种重试策略的缺点是实现起来比较复杂需要考虑重试次数和时间的关系以及设置合理的上限和下限值。另外这种重试策略也可能会导致用户等待时间过长影响用户体验。重试的次数如何设置 重试的次数通常建议设为 3 次。大部分情况下我们还是更建议使用梯度间隔重试策略。如何实现重试 如果要手动编写代码实现重试逻辑的话可以通过循环例如 while 或 for 循环或者递归实现。 不过一般不建议自己动手实现有很多第三方开源库提供了更完善的重试机制实现例如 Spring Retry、Resilience4j、Guava Retrying。
什么是重试幂等 超时和重试机制在实际项目中使用的话需要注意保证同一个请求没有被多次执行。 什么情况下会出现一个请求被多次执行呢客户端等待服务端完成请求完成超时但此时服务端已经执行了请求只是由于短暂的网络波动导致响应在发送给客户端的过程中延迟了。 举个例子用户支付购买某个课程结果用户支付的请求由于重试的问题导致用户购买同一门课程支付了两次。对于这种情况我们在执行用户购买课程的请求的时候需要判断一下用户是否已经购买过。这样的话就不会因为重试的问题导致重复购买了。
性能测试
性能测试是什么
性能测试一般情况下都是由测试这个职位去做的了解性能测试的指标、分类以及工具等知识有助于我们更好地去写出性能更好的程序。不同角色看网站性能 用户在体验我们系统的时候往往根据你的响应速度的快慢来评判你的网站的性能。开发人员系统处理用户请求的速度。 项目架构是分布式的吗用到了缓存和消息队列没有高并发的业务有没有特殊处理数据库设计是否合理系统用到的算法是否还需要优化系统是否存在内存泄露的问题项目使用的 Redis 缓存多大服务器性能如何用的是机械硬盘还是固态硬盘测试人员: 根据性能测试工具来测试然后一般会做出一个表格。这个表格可能会涵盖下面这些重要的内容响应时间请求成功率吞吐量运维人员倾向于根据基础设施和资源的利用率来判断网站的性能比如我们的服务器资源使用是否合理、数据库资源是否存在滥用的情况、当然这是传统的运维人员现在 Devops 火起来后单纯干运维的很少了。
如何进行性能测试 性能测试需要注意的点 1、性能测试之前更需要你了解当前的系统的业务场景。 对系统业务了解的不够深刻我们很容易犯测试方向偏执的错误从而导致我们忽略了对系统某些更需要性能测试的地方进行测试。 2、当前系统所留下的历史数据非常重要一般情况下我们可以通过相应的些历史数据初步判定这个系统哪些接口调用的比较多、哪些 service 承受的压力最大。 性能测试的指标 1、响应时间用户发出请求到用户收到系统处理结果所需要的时间。比较出名的 2-5-8 原则是这样描述的通常来说2 到 5 秒页面体验会比较好5 到 8 秒还可以接受8 秒以上基本就很难接受了。一般取多次请求的平均响应时间。 2、并发数系统能同时处理请求的数目。 3、吞吐量单位时间内系统处理的请求数量。 衡量吞吐量有几个重要的参数QPSTPS、并发数、响应时间。 QPSQuery Per Second服务器每秒可以执行的查询次数 TPSTransaction Per Second服务器每秒处理的事务数这里的一个事务可以理解为客户发出请求到收到服务器的过程 4、理清他们的概念 QPSTPS 并发数/平均响应时间 并发数 QPS*平均响应时间 5、QPS vs TPS QPS 基本类似于 TPS但是不同的是对于一个页面的一次访问形成一个 TPS但一次页面请求可能产生多次对服务器的请求服务器对这些请求就可计入“QPS”之中。 6、性能计数器 性能计数器是描述服务器或者操作系统的一些数据指标如内存使用、CPU 使用、磁盘与网络 I/O 等情况。 常见的性能测试 性能测试 性能测试方法是通过测试工具模拟用户请求系统目的主要是为了测试系统的性能是否满足要求。通俗地说这种方法就是要在特定的运行条件下验证系统的能力状态。 负载测试 对被测试的系统继续加大请求压力直到服务器的某个资源已经达到饱和了比如系统的缓存已经不够用了或者系统的响应时间已经不满足要求了。负载测试说白点就是测试系统的上限。 压力测试 不去管系统资源的使用情况对系统继续加大请求压力直到服务器崩溃无法再继续提供服务。 稳定性测试 模拟真实场景给系统一定压力看看业务是否能稳定运行。 常用性能测试工具 后端常用 1、JmeterApache JMeter 是 JAVA 开发的性能测试工具。 2、LoadRunner一款商业的性能测试工具。 3、Galtling一款基于 Scala 开发的高性能服务器性能测试工具。 4、ab全称为 Apache Bench 。Apache 旗下的一款测试工具非常实用。 前端常用 1、Fiddler抓包工具它可以修改请求的数据甚至可以修改服务器返回的数据功能非常强大是 Web 调试的利器。 2、HttpWatch: 可用于录制 HTTP 请求信息的工具。
常见的性能优化策略
系统是否需要缓存系统架构本身是不是就有问题系统是否存在死锁的地方系统是否存在内存泄漏Java 的自动回收内存虽然很方便但是有时候代码写的不好真的会造成内存泄漏数据库索引使用是否合理
附参考资料
123