大型网站架构:高性能

说明:此次分享,整理有独立的 keynote.

目标:高性能的网站,要求响应时间短、支持高并发

几个问题:

  • 指标:衡量网站性能的指标,有哪些?牛不牛逼,不能听你瞎说,总得有个衡量标准,谁的高,谁在这方面就牛逼
  • 监控:如何收集指标信息?
  • 改进:不同指标的改进措施和原理?

不同人,不同视角,关注的网站高性能指标不同:

  1. 用户:用户感觉到的,网站响应速度
    1. 网站响应时间:
      1. 服务器处理时间
      2. 网络传输时间
      3. 浏览器 HTML 渲染时间
  2. 开发人员:
    1. 请求处理时间:
      1. 思考:端到端的延时?不仅仅是服务器的处理时间,此时,需要前端页面中观察请求的响应时间。
    2. 系统吞吐量
      1. 思考:什么是吞吐量?跟并发量有什么关系?QPS?TPS?
    3. 高并发处理能力
      1. QPS 的意义?高并发,就是 QPS? 1s = 1000ms,可能包含好多批次的处理。
  3. 运维人员:
    1. 基础设施:资源利用率
      1. OS 层级
      2. 运营商的网络利用率
      3. 硬件配置
      4. 数据中心网络架构

app-server-general-flow.pnguploading.4e448015.gif转存失败重新上传取消

排除不可控的指标,在研发和运维角度,有一些通用的指标:

  1. 响应时间:服务器侧,收到请求到返回响应的时间
  2. 并发数
  3. 吞吐量
  4. 性能计数器:OS 层级的统计信息,CPU、Mem、网络、磁盘等

按照层级,分类如下:

  • App 级:
    • 响应时间
    • 吞吐量
  • OS 级:
    • 性能计数器

2.2.1. 响应时间

几个常见的时间:

  • CPU 执行时间?2 GHz,对应 0.5 ns,实际涉及到读取指令,一般在 us 量级
  • 内存读取数据:1~n x 10 us
  • 通过网络读取数据时间?0~1ms (跟距离和跳数相关)
  • 机械磁盘读取数据:1~5 ms,7200 rpm (round per minute)
  • 数据库索引方式,查询记录:2~10 ms

其他时间汇总:

general-time-level-of-web-flow.pnguploading.4e448015.gif转存失败重新上传取消

2.2.2. 并发数

并发数:同时处理请求的数据。 简单的说,就是同时处理的线程数量。

2.2.3. 吞吐量

吞吐量:单位时间内处理的请求数量。

具体衡量指标:

  1. TPS:每秒处理的事务数量
  2. QPS:每秒处理的查询请求数量
  3. HPS:每秒处理的 HTTP 请求数量

思考:

并发数 vs. 吞吐量?

Re:

  1. 随着「并发数」增加,系统「吞吐量」会上升
  2. 达到系统极限后,随着「并发数」增加,系统吞吐量会降低,最后系统资源耗尽,崩溃

parallel-with-tps-trend.pnguploading.4e448015.gif转存失败重新上传取消

2.2.4. 性能计数器

性能计数器:描述硬件/OS 级别的数据指标,例如:系统负载、线程数、内存使用、CPU 使用、磁盘 IO 、网络 IO 等。

部分指标,简单解释:

  • 系统负载:system load,(正在执行 + 排队执行的线程)/ CPU 核心数目,一般设置 0.3,0.5,0.7,1 几个指标,表示不同的状态。

测量指标,常见的实现:

  • OS、JVM:性能计数器
    • Ganglia、Zabbix、Falcon 等
  • App 级别:响应时间、吞吐量
    • Spring AOP 定制
    • Nginx 访问日志
    • Web Server 访问日志

有了监控,就可以进行压力测试了。

压力测试:构造模拟场景,测试系统在不同压力下,响应时间、并发数、吞吐量、性能计数器等指标的表现。

测试方法:

  1. 不断增加请求数量
  2. 2 个请求之间,增加随机的等待时间
  3. 不均匀、突发式、间断性

测试,有一个大前提:做好指标监控

从「浏览器」角度,可优化的地方:

  1. 减少页面中 HTTP 请求次数:css、js、image 的请求
    1. 合并请求
    2. 浏览器缓存:HTTP response 中 HTTP Header 中添加 Cache-Control 和 Expires 属性
  2. 减少请求的数据大小:
    1. 压缩:服务器端压缩、浏览器端解压缩,需要 balance,因为压缩也需要时间,网络良好时,不建议压缩
    2. Cookie 简化:不必要的数据,不添加到 Cookie 中
  3. 浏览器渲染机制:下载完 css 之后,才会去渲染
    1. CSS 链接放在页面最前面
  4. 浏览器「就近获取」资源:
    1. CDN 加速:请求图片、css、js等静态资源时,就近运营商和机房获取

从「服务器」角度,可优化的地方:

  1. 缓存:要保证数据一致性
    1. 本地缓存:无法保证「数据一致性」
    2. 分布式缓存:通过「主动失效缓存」,能保证「数据一致性」
  2. 消息队列:异步操作,及时响应
    1. 异步操作带来的问题:无法 Fail-Fast,需要同步优化业务流程
  3. 集群:单台机器处理能力有限,扩充为集群
    1. 反向代理:缓存 + 负载均衡
  4. 优化代码:
    1. 多线程
    2. 资源复用

app-server-general-flow-single-db.pnguploading.4e448015.gif转存失败重新上传取消

4.2.1. 缓存

衡量缓存的指标:缓存命中率。(命中率:从缓存请求数据的次数 / 从缓存读取到数据的次数)

合理使用缓存:

  1. 「一写多读」的数据访问模型
  2. 有明显的「热点数据」
  3. 恰当的「数据一致性」策略
  4. 缓存可用性的预期:高可用、低可用?
  5. 缓存预热
  6. 防止缓存击穿

分布式缓存,本质是「集群」,关键问题:

  1. 如何保证,同一个 key 放在同一个「服务器节点」?
  2. 如果「服务器节点」失效,如何保证不影响「其他服务器节点」的正常工作?
    1. 正常工作:Client 将 KeyA 放到了 Node B 上,Node A 失效后,Client 仍然知道去 Node B 上,读取 KeyA 的缓存数据?
  3. 如果「服务器节点」新增了一个,如何保证不影响「其他服务器节点」的正常工作?
    1. 正常工作:Client 将 KeyA 放到了 Node B 上,新增 Node C后,Client 仍然知道去 Node B 上,读取 KeyA 的缓存数据?

解决分布式缓存集群问题一致性 Hash 算法

一致性 Hash 算法:本质,Client 使用「一致性 Hash 环」保存所有的「集群节点」,计算出 key 对应的 「Node」后,就对相应的 Node 进行读写操作。

更多细节,参考:

  1. 什么是一致性Hash算法?

  2. 对一致性Hash算法,Java代码实现的深入研究

疑问:分布式缓存集群中,节点的增减,如何通知到 Client ?

Re:每次在集中的地点,进行一致性 hash 运算。

app-server-general-flow-with-cache.pnguploading.4e448015.gif转存失败重新上传取消

4.2.2. MQ:异步操作

将需要处理的业务流程,暂时存放到 MQ 中,提前返回用户响应信息。

MQ 的注意事项:

延迟处理业务,需要同步优化「业务流程」

Note: 技术上很棘手的问题,可以优化业务流程来解决。

app-server-general-flow-with-mq.pnguploading.4e448015.gif转存失败重新上传取消

4.2.3. 集群

集群方式:减弱单机的压力,通过多台机器分担并发请求,提升整体集群的吞吐量。’

app-server-general-flow-with-reverse-proxy.pnguploading.4e448015.gif转存失败重新上传取消

4.2.4. 代码优化

优化代码,提升系统性能。

常用方法:

  1. 多线程:多线程并发处理
  2. 资源复用:Spring MVC 中单例的对象、数据库连接的连接池、线程池

4.2.4.1. 多线程

多线程工作,提升处理效率,疑问:

  1. 是不是线程数量越多越好?
  2. 有没有极限?
  3. 有没有理论最大值?
  4. 如何确定最优的线程数量?

多线程方式,能够提升系统吞吐量,本质优化点:线程的 IO 时间 » 线程的 CPU 执行时间

采用多线程,实际是,在「一个线程 IO 执行过程中」,尽可能启动多个线程,使用「CPU 资源」。

cpu-time-with-io-time-show.pnguploading.4e448015.gif转存失败重新上传取消

所以,理论上,最佳的「并发线程数量」:

T1/(T1-T2) x CPU 核心数

Note: IO 执行时间 除以 CPU 执行时间,就是可以新增的线程个数。

因此,需要根据具体业务场景,判断是否适合采用「多线程」:

  1. 计算密集型业务场景:不适合过多的「多线程」,只要求「线程数」=「CPU核心数」
  2. IO 频繁型业务场景:可采用「多线程」策略,增加系统吞吐量。

多线程,就涉及到「线程安全」问题,解决策略:

  1. 对象设计为「无状态」
  2. 使用局部变量
  3. 并发放问资源时,采用「锁」

4.2.4.2. 资源复用

线程池、连接池等。

几点:

  1. 「固态硬盘」替换机械磁盘
  2. 数据结构:B+ 树或者 LSM 树,充分利用「磁盘局部性原理」:机械磁盘特性,顺序读写快、随机读写慢。
  3. RAID(廉价磁盘冗余阵列)和 HDFS 提升:可用性、容错性,
  4. Note:提升磁盘 IO 的访问速率,单块磁盘,IO 有上限,数据分不到多块磁盘上,能够并发读写。

RAID vs. HDFS,本质都是数据冗余,数据分散存储,提升读取速度,适用场景:

  1. 传统系统、高可用系统,SQL 数据库,建议采用 RAID10 进行一次数据操作
  2. 现在的海量数据分析系统,可以直接上 HDFS
  • 《大型网站技术架构:核心原理与案例分析》第4章 瞬时响应:网站的高性能架构
在使用Python来安装geopandas包时,由于geopandas依赖于几个其他的Python库(如GDAL, Fiona, Pyproj, Shapely等),因此安装过程可能需要一些额外的步骤。以下是一个基本的安装指南,适用于大多数用户: 使用pip安装 确保Python和pip已安装: 首先,确保你的计算机上已安装了Python和pip。pip是Python的包管理工具,用于安装和管理Python包。 安装依赖库: 由于geopandas依赖于GDAL, Fiona, Pyproj, Shapely等库,你可能需要先安装这些库。通常,你可以通过pip直接安装这些库,但有时候可能需要从其他源下载预编译的二进制包(wheel文件),特别是GDAL和Fiona,因为它们可能包含一些系统级的依赖。 bash pip install GDAL Fiona Pyproj Shapely 注意:在某些系统上,直接使用pip安装GDAL和Fiona可能会遇到问题,因为它们需要编译一些C/C++代码。如果遇到问题,你可以考虑使用conda(一个Python包、依赖和环境管理器)来安装这些库,或者从Unofficial Windows Binaries for Python Extension Packages这样的网站下载预编译的wheel文件。 安装geopandas: 在安装了所有依赖库之后,你可以使用pip来安装geopandas。 bash pip install geopandas 使用conda安装 如果你正在使用conda作为你的Python包管理器,那么安装geopandas和它的依赖可能会更简单一些。 创建一个新的conda环境(可选,但推荐): bash conda create -n geoenv python=3.x anaconda conda activate geoenv 其中3.x是你希望使用的Python版本。 安装geopandas: 使用conda-forge频道来安装geopandas,因为它提供了许多地理空间相关的包。 bash conda install -c conda-forge geopandas 这条命令会自动安装geopandas及其所有依赖。 注意事项 如果你在安装过程中遇到任何问题,比如编译错误或依赖问题,请检查你的Python版本和pip/conda的版本是否是最新的,或者尝试在不同的环境中安装。 某些库(如GDAL)可能需要额外的系统级依赖,如地理空间库(如PROJ和GEOS)。这些依赖可能需要单独安装,具体取决于你的操作系统。 如果你在Windows上遇到问题,并且pip安装失败,尝试从Unofficial Windows Binaries for Python Extension Packages网站下载相应的wheel文件,并使用pip进行安装。 脚本示例 虽然你的问题主要是关于如何安装geopandas,但如果你想要一个Python脚本来重命名文件夹下的文件,在原始名字前面加上字符串"geopandas",以下是一个简单的示例: python import os # 指定文件夹路径 folder_path = 'path/to/your/folder' # 遍历文件夹中的文件 for filename in os.listdir(folder_path): # 构造原始文件路径 old_file_path = os.path.join(folder_path, filename) # 构造新文件名 new_filename = 'geopandas_' + filename # 构造新文件路径 new_file_path = os.path.join(folder_path, new_filename) # 重命名文件 os.rename(old_file_path, new_file_path) print(f'Renamed "{filename}" to "{new_filename}"') 请确保将'path/to/your/folder'替换为你想要重命名文件的实际文件夹路径。
在使用Python来安装geopandas包时,由于geopandas依赖于几个其他的Python库(如GDAL, Fiona, Pyproj, Shapely等),因此安装过程可能需要一些额外的步骤。以下是一个基本的安装指南,适用于大多数用户: 使用pip安装 确保Python和pip已安装: 首先,确保你的计算机上已安装了Python和pip。pip是Python的包管理工具,用于安装和管理Python包。 安装依赖库: 由于geopandas依赖于GDAL, Fiona, Pyproj, Shapely等库,你可能需要先安装这些库。通常,你可以通过pip直接安装这些库,但有时候可能需要从其他源下载预编译的二进制包(wheel文件),特别是GDAL和Fiona,因为它们可能包含一些系统级的依赖。 bash pip install GDAL Fiona Pyproj Shapely 注意:在某些系统上,直接使用pip安装GDAL和Fiona可能会遇到问题,因为它们需要编译一些C/C++代码。如果遇到问题,你可以考虑使用conda(一个Python包、依赖和环境管理器)来安装这些库,或者从Unofficial Windows Binaries for Python Extension Packages这样的网站下载预编译的wheel文件。 安装geopandas: 在安装了所有依赖库之后,你可以使用pip来安装geopandas。 bash pip install geopandas 使用conda安装 如果你正在使用conda作为你的Python包管理器,那么安装geopandas和它的依赖可能会更简单一些。 创建一个新的conda环境(可选,但推荐): bash conda create -n geoenv python=3.x anaconda conda activate geoenv 其中3.x是你希望使用的Python版本。 安装geopandas: 使用conda-forge频道来安装geopandas,因为它提供了许多地理空间相关的包。 bash conda install -c conda-forge geopandas 这条命令会自动安装geopandas及其所有依赖。 注意事项 如果你在安装过程中遇到任何问题,比如编译错误或依赖问题,请检查你的Python版本和pip/conda的版本是否是最新的,或者尝试在不同的环境中安装。 某些库(如GDAL)可能需要额外的系统级依赖,如地理空间库(如PROJ和GEOS)。这些依赖可能需要单独安装,具体取决于你的操作系统。 如果你在Windows上遇到问题,并且pip安装失败,尝试从Unofficial Windows Binaries for Python Extension Packages网站下载相应的wheel文件,并使用pip进行安装。 脚本示例 虽然你的问题主要是关于如何安装geopandas,但如果你想要一个Python脚本来重命名文件夹下的文件,在原始名字前面加上字符串"geopandas",以下是一个简单的示例: python import os # 指定文件夹路径 folder_path = 'path/to/your/folder' # 遍历文件夹中的文件 for filename in os.listdir(folder_path): # 构造原始文件路径 old_file_path = os.path.join(folder_path, filename) # 构造新文件名 new_filename = 'geopandas_' + filename # 构造新文件路径 new_file_path = os.path.join(folder_path, new_filename) # 重命名文件 os.rename(old_file_path, new_file_path) print(f'Renamed "{filename}" to "{new_filename}"') 请确保将'path/to/your/folder'替换为你想要重命名文件的实际文件夹路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值