侧边栏壁纸
  • 累计撰写 120 篇文章
  • 累计创建 281 个标签
  • 累计收到 11 条评论
标签搜索
隐藏侧边栏

《亿级流量网站架构》读书笔记

骐骏
2018-08-10 / 0 评论 / 0 点赞 / 470 阅读 / 0 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2018-08-10,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。
  1. 限流详解
    1. 限流算法
      1. 令牌法:每秒产生指定数量令牌,如果能够获得令牌则不限流;无法获得令牌则限流
      2. 漏斗法:类似于一边进水一边放水;将请求放入桶中如果桶没满,正常处理,如果桶满,则拒绝请求。
    2. 应用级限流
    3. 分布式限流
      1. redis + lua
      2. nginx + lua
    4. 接入层限流 (nginx等)
      1. ngx_http_limit_conn_module limit_conn 对某个key对应的总的网络连接数进行限制 示例: // 按域名限流 limit_conn_zone $serve_name zone=one:10m rate=1r/s; location ~* .htm$ { limit_conn zone=one burst=5 nodelay; proxy_pass http://backend_tomcat; }
      2. ngx_http_limit_req_module limit_req 对某个key对应的请求进行限流,是使用漏斗算法实现的 // 按ip限流 limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; location ~* .htm$ { limit_req zone=one burst=5 nodelay; proxy_pass http://backend_tomcat; } ngx_http_limit_conn_module,ngx_http_limit_req_module 两个模块都可以针对Ip或域名进行限流
      3. lua-resty-limit-traffic openResty提供的lua限流模块 可以灵活编程限流
    5. 节流

      在特定的时间窗口内对重复的相同的时间最多只处理一次,或者想限制多个连续相同的时间最小执行时间间隔

      1. 三种实现方式 throttleFirst throttleLast throttleWithTimeout
      2. throttleFirst/throttleLast是指在一个时间窗口期内如果有多个相同的请求只处理第一个/最后一个。比如连续拖拽浏览器窗口,只响应最后一次
      3. throttleWithTimeout限制两个连续事件的执行时间不得小于某个时间窗口。比如搜索关键字自动补全,利用该方式可以减少网络请求
  2. 降级
    1. 降级预案 分级降级
      1. 一般:因网络抖动或项目上线造成的超时,可自动降级
      2. 警告:一段时间内成功率有波动(95%~100%),可自动降级,并发送告警
      3. 错误:可用率低于90%,或访问量突增达到系统阈值,要根据情况实现自动降级或人工降级
      4. 严重错误:由于特殊原因出现的错误,需要实现紧急人工降级
    2. 降级分类
      1. 自动降级、人工降级
      2. 读服务降级、写服务降级
      3. 按处于系统的层级分为:多级降级
        1. 页面降级
        2. 页面片段降级
        3. 页面异步请求降级
        4. 服务功能降级
        5. 读降级
        6. 写降级
        7. 爬虫降级:识别出爬虫直接拒绝
        8. 风控降级:拒绝高风险用户
    3. 使用Hystrix实现降级
  3. 超时与重试机制
    1. 零散知识
      1. 写服务是幂等才可以使用重试
      2. 如果重试次数太多,则可能造成请求剧增
      3. 如果不设置超时时间,会造成响应慢,请求累积
    2. 代理层超时设置(以nginx为例)
      1. nginx有四种超时设置:
        1. 客户端超时设置
        2. DNS解析超时
        3. 代理超时
        4. 如果使用ngx_lua,则有lua相关超时设置
    3. web容器超时机制 (以tomcat为例)
      1. connectionTimeout:配置与客户端建立连接的超时时间,从接收到连接后,在配置的时间内没有接收到客户端请求行,将被认定为连接超时,默认为60000ms
    4. 中间件客户端超时与重试
    5. 数据库客户端超时
    6. Nosql客户端超时
    7. 业务超时
      1. 任务型超时:比如订单超时未支付,可以通过Worker定期扫描数据库修改状态。
      2. 服务调用型超时,比如,某个服务的全局超时时间是500ms,但是有多处服务调用,每处服务调用的超时时间可能不一样,此时可以使用Future来解决,如:Future.get(3000,TimeUnit.MILLISECONDE) 8.前端Ajax超时
      3. 设置timeout属性
          $.ajax({
              url:xxxx,
              timeout:2000,
              success:function(){
      
              }
          })
      
  4. 回滚机制
    回滚是指当程序或数据出错时,将程序或数据恢复到最近一个正确的版本,常见的如事物回滚,代码库回滚,部署版本回滚,数据库版本回滚,静态资源版本回滚。通过回滚机制可以保证系统在某些场景下的高可用。
    1. 事物回滚
      1. 单数据库回滚
      2. 分布式事物回滚
        1. 使用两阶段提交,三阶段提交协议,这种方式实现回滚难度较低,但对性能影响比较大。
        2. 保证最终一致性,而不是强一致性,常见方法:事物表、消息队列、补偿机制(执行/回滚)、TCC(预占/确认/取消)、Sagas模式(拆分事物+补偿模式)等实现最终一致性。
    2. 代码回滚
    3. 部署回滚
      1. 部署版本化
      2. 小版本增量发布
      3. 大版本灰度发布
      4. 架构升级并发发布

        架构升级后,我们不清楚新版本功能是否正常,因此,新老版本会共存一段时间。等所有流量迁移到新版本集群后,将老版本集群下线。
        接入层要能够灵活控制流量的方向

    4. 数据版本回滚
    5. 静态资源版本回滚
  5. 压测与预案
    1. 压测一般指性能压力测试,用来评估系统的稳定性和性能
    2. 线下压测 -- JMeter Apache ab测试
    3. 线上压测 读压测、写压测、混合压测
      1. 仿真压测 使用TCPCopy将线上请求复制到测试环境,并可发大N倍
      2. 隔离集群压测 将需要压测大系统在线上集群隔离出来
      3. 单机压测 通过单机压测估算出单机极限处理能力,继而估算集群极限能力,但由于集群系统收到依赖但系统的影响所以该估算并不准确
    4. 系统优化和容灾
    5. 制定应急预案
  6. 高并发

    1. 应用级缓存
      1. 分类
        1. 堆缓存
        2. 堆外缓存
        3. 磁盘缓存
        4. 分布式缓存
        5. 多级缓存
      2. 多级缓存:
        1. 本地缓存过期时间设置为远程缓存的一半,防止本地缓存时间过长造成多实例间数据不一致
        2. 写缓存的时候,先写本地缓存,然后异步更新远程缓存;异步更新远程缓存是为了更快的相应用户请求。
        3. 读缓存时,先读本地缓存,本地缓存不命中再批量查询远程缓存
      3. 缓存使用模式实践
        1. 主要分为两大类:
          1. Cache-Aside 由业务代码直接维护缓存
          2. Cache-As-SoR(read-through(读穿透),write-through(写穿透),write-behind(回写,即异步写)): 业务代码只操作缓存,然后委托给缓存去操作SoR
            1. read-through: 业务代码调用cache,如果未命中由cache回源到SoR
            2. write-through:业务代码调用cache写,然后由cache负责写缓存和SoR,同步写cache和SoR
            3. write-behind:业务代码调用cache写,然后由cache负责写缓存和SoR,异步写cache和SoR,异步后可以实现批量写、合并写、延时、限流
        2. 名词解释
          1. SoR 即system of record 记录系统或者叫做数据源,即实际存储原始数据的系统
          2. Cache:缓存,SoR的快照 cache的访问速度要比SoR要快
          3. 回源:即到数据源头查找数据
    2. 数据库连接池
      1. mysql 空闲连接8小时自动断开 1.在连接池中配置 testOnBorrow=true 在数据库连接池中取连接时先验证连接的有效性;validationQuery 创建连接时验证
    3. HTTP缓存
    4. 线程池:减少线程创建,销毁的耗时
      1. 线程池分类:
      2. tomcat线程池:
        <Connector port="8010" protocol="AJP/1.3" redirectPort="8443"   acceptCount="100" maxConnections="200" minSpareThreads="10" maxThreads="200"/>
        
        

        acceptCount:最多接收多少请求进入等待队列,超过后直接拒绝

        maxConnections:tomcat的最大并发数,当超过后还会接收请求并放到等待队列(等待队列大小有acceptCont决定)

        配置方式二、利用Executor


        <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" deamon="true" minSpareThread="25" maxThreads="200" maxIdelTime="60000" maxQueueSize="Integer.MAX_VALUE "> <Connector port="8010" protocol="AJP/1.3" redirectPort="8443" excutor="tomcatThreadPool" />

        使用org.apache.catalina.Executor实现,表示其中一个可以在多个connector间共享的线程池,而且有更丰富的配置

    5. 异步并发实战
      1. 同步阻塞
      2. 异步Future
      3. 异步callback
      4. 异步编排 completableFuture
      5. 异步Web服务实现
      6. 请求缓存
      7. 请求合并
    6. 如何实现扩容

      1. 扩容的三个步骤
        1. 尝试简单扩容解决
        2. 水平拆分和垂直拆分数据库/应用系统的伸缩性,即通过扩容提升系统负载能力
        3. 根据现有系统特性,从架构层面进行重构甚至重新设计
      2. 单体应用垂直扩容
        1. 增大机器内存,增加核数,换固态硬盘,增加磁盘容量
      3. 单体应用水平扩容
        1. 增加镜像,利用负载均衡器负载新增加的应用
      4. 应用拆分:按业务将一个大系统拆分为多个子系统
      5. 数据库拆分
        1. 跨库join可以考虑通过全局表、ES搜索等异构数据机制来实现
        2. 还要考虑分布式事务
      6. 扩容总结:应用扩容可以通过部署更多的实例来解决,无法部署更多实例时,就需要考虑拆分或者重新架构。而数据库扩容首先是硬件层面的,然后按照业务垂直拆分,接着水平拆分,最后根据场景进行读写分离,还可以将读流量分流到NoSql中
      7. 数据库拆分示例:
        1. 数据库分库分表可以在应用层实现也可以在中间件层实现
        2. sharing-jdbc使用
        3. 数据异构

          数据异构主要按照不同查询维度建立表结构,这样就可以按照不同的维度进行查询。数据异构有查询维度异构,聚合数据异构等。查询异构示例:将订单表按商家订单、用户订单异构;或者将订单信息存储到ES中。聚合异构示例:将存储到多个表中的商品基本信息、属性、图片等聚合到kv存储集群中。

      8. 任务系统扩容
    7. 队列
      1. 使用队列进行异步处理、系统解耦、数据同步、流量削峰、扩展性、缓存等。在使用队列时需要考虑是否需要保证消息的有序性及如何保证,是否能重复消费及如何保证重复消费的幂等性。
      2. 队列常用方式
        1. 缓冲队列
        2. 任务队列
        3. 消息队列
        4. 请求队列
        5. 数据总线队列
        6. 混合队列
  7. 京东商品详情页实践 (略)
  8. 使用OpenResty开发高性能web应用
    1. nginx+lua的常见实践和场景:动态负载均衡、防火墙(DDOS,IP/url/userAgent/referer黑名单、防盗链)、限流、降级、A/B测试和灰度发布、多级缓存、服务器请求合并、服务质量监控
  9. 应用数据静态化架构高性能单页web应用
    1. 将数据和模板都动态存储
0

评论区