Skip to content

Commit

Permalink
fix typo
Browse files Browse the repository at this point in the history
  • Loading branch information
isno committed Feb 1, 2025
1 parent b7f1c2c commit 612257f
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 38 deletions.
38 changes: 22 additions & 16 deletions Observability/logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@

图 9-6 展示了一套基于 Elastic Stack 的日志处理方案:

- **数据收集**:Beats 组件部署在业务所在节点,负责收集原始的日志数据
- **数据缓冲**:使用 RabbitMQ 消息队列缓冲数据,提高数据吞吐量
- **数据收集**:Beats 组件部署在业务所在节点,负责收集原始的日志数据
- **数据缓冲**:使用 RabbitMQ 消息队列缓冲数据,提高数据吞吐量
- **数据清洗**:数据通过 Logstash 进行清洗。
- **数据存储**:清洗后的数据存储在 Elasticsearch 集群中,它负责索引日志数据、查询聚合等核心功能
- **数据存储**:清洗后的数据存储在 Elasticsearch 集群中,它负责索引日志数据、查询聚合等核心功能
- **数据可视化**:Kibana 负责数据检索、分析与可视化,必要时可部署 Nginx 实现访问控制。

:::center
Expand Down Expand Up @@ -48,7 +48,7 @@ Elasticsearch 能够在海量数据中迅速检索关键词,其关键技术之
Elasticsearch 的另一项关键技术是“分片”(sharding)。每个分片相当于一个独立的 Lucene 实例,类似于一个完整的数据库。在文档(Elasticsearch 数据的基本单位)写入时,Elasticsearch 会根据哈希函数(通常基于文档 ID)计算出文档所属的分片,从而将文档均匀分配到不同的分片;查询时,多个分片并行计算,Elasticsearch 将结果聚合后再返回给客户端。

为了追求极致的查询性能,Elasticsearch 也付出了以下代价:
- **写入吞吐量下降**:文档写入需要进行分词、构建排序表等操作,这些都是 CPU 和内存密集型的,会导致写入性能下降
- **写入吞吐量下降**:文档写入需要进行分词、构建排序表等操作,这些都是 CPU 和内存密集型的,会导致写入性能下降
- **存储空间占用高**:Elasticsearch 不仅存储原始数据和反向索引,为了加速分析能力,可能还额外存储一份列式数据(Column-oriented Data);其次,为了避免单点故障,Elasticsearch 会为每个分片创建一个或多个副本副本(Replica),这导致 Elasticsearch 会占用极大的存储空间。


Expand All @@ -57,11 +57,11 @@ Elasticsearch 的另一项关键技术是“分片”(sharding)。每个分
Grafana Loki 是由 Grafana Labs 开发的一款日志聚合系统,其设计灵感来源于 Prometheus,目标是成为“日志领域的 Prometheus”。与 Elastic Stack 相比,Loki 具有轻量、低成本和与 Kubernetes 高度集成等特点。

Loki 的架构如图 9-7 所示,其组件以及作用如下:
- **日志代理**(Promtail):负责从多种来源(如文件系统、云日志服务)收集日志,并将其格式化后发送至 Loki 系统
- **分发器**(Distributor):接收 Promtail 或其他来源发送的日志,验证日志的完整性,并根据分片规则将日志分发到合适的 Ingester 节点
- **写入器**(Ingester):负责日志的临时存储和索引,将日志数据分段存储,并定期将数据持久化到长久存储(如对象存储)
- **查询器**(Querier):执行用户的日志查询请求,从存储中提取所需数据并返回结果
- **查询前端**(Query Frontend):用于优化查询性能,负责分解复杂查询、管理缓存以及合并查询结果,提高查询效率和用户体验
- **日志代理**(Promtail):负责从多种来源(如文件系统、云日志服务)收集日志,并将其格式化后发送至 Loki 系统
- **分发器**(Distributor):接收 Promtail 或其他来源发送的日志,验证日志的完整性,并根据分片规则将日志分发到合适的 Ingester 节点
- **写入器**(Ingester):负责日志的临时存储和索引,将日志数据分段存储,并定期将数据持久化到长久存储(如对象存储)
- **查询器**(Querier):执行用户的日志查询请求,从存储中提取所需数据并返回结果
- **查询前端**(Query Frontend):用于优化查询性能,负责分解复杂查询、管理缓存以及合并查询结果,提高查询效率和用户体验
- **规则处理器**(Ruler):处理监控和告警规则,对日志数据执行周期性评估,并根据预定义规则触发告警或生成报告。

:::center
Expand All @@ -71,8 +71,8 @@ Loki 的架构如图 9-7 所示,其组件以及作用如下:

Loki 的主要特点是,只对日志的元数据(如标签、时间戳)建立索引,而不对原始日志数据进行索引。在 Loki 的存储模型中,数据有以下两种类型:

- **索引**(Indexes):Loki 的索引仅包含日志流的标签(如日志的来源、应用名、主机名等)和时间戳,并将其与相应的块关联。
- ****(Chunks):块是 Loki 用来存储实际日志数据的基本单元。每个日志条目都会被压缩成一个块,并存储在持久化存储介质中,如对象存储(例如 Amazon S3、GCP、MinIO)或本地文件系统。
- **索引**(Indexes):Loki 的索引仅包含日志标签(如日志的来源、应用名、主机名等)和时间戳。索引与相应的块关联;
- ****(Chunks):用来存储原始日志数据的基本单元。原始日志数据会被压缩成“块”,存储在持久化存储介质中,如对象存储(例如 Amazon S3、GCP、MinIO)或本地文件系统。

不难看出,Loki 通过仅索引元数据、以及索引和块的分离存储设计,让其在处理大规模日志数据时具有明显的成本优势。

Expand All @@ -93,7 +93,9 @@ ClickHouse 是由俄罗斯 Yandex 公司[^2]于 2008 年开发的开源列式数
| #2 | 89953706054 | 78 | Mission| 1 | 2016-05-18 07:38:00| |
| #N | ...| ...| ...| ... | ...

在行式数据库中,一行数据会在物理存储介质中紧密相邻。如果要执行下面的 SQL 来统计某个产品的销售额,行式数据库需要加载整个表的所有行到内存,进行扫描和过滤(检查是否符合 WHERE 条件)。过滤出目标行后,若有聚合函数(如 SUM、MAX、MIN),还需要进行相应的计算和排序,最后才会过滤掉不必要的列,整个过程可能非常耗时。
在行式数据库中,一行数据会在物理存储介质中紧密相邻。

如果要执行下面的 SQL 来统计某个产品的销售额,行式数据库需要加载整个表的所有行到内存,进行扫描和过滤(检查是否符合 WHERE 条件)。过滤出目标行后,若有聚合函数(如 SUM、MAX、MIN),还需要进行相应的计算和排序,最后才会过滤掉不必要的列,整个过程可能非常耗时。

```SQL
// 统计销售额
Expand All @@ -112,10 +114,12 @@ SELECT sum(sales) AS count FROM 表 WHERE ProductId=90329509958
|GoodEvent: | 1| 1| 1| ...|
|CreateTime: | 2016-05-18 05:19:20 |2016-05-18 08:10:20 |2016-05-18 07:38:00 |...|

此外,列式存储通常与数据压缩伴生。数据压缩的本质是通过一定步长对数据进行匹配扫描,发现重复部分后进行编码转换。面向列式的存储,同一列的数据类型和语义相同,重复项的可能性更高,因此自然有着更高的压缩率。ClickHouse 更进一步的允许用户根据每列数据的特性选择最适合的压缩算法。如下 SQL 示例,创建 MergeTree 类型 example 表,其中:
此外,列式存储通常与数据压缩伴生。数据压缩的本质是通过一定步长对数据进行匹配扫描,发现重复部分后进行编码转换。面向列式的存储,同一列的数据类型和语义相同,重复项的可能性更高,因此自然有着更高的压缩率。

ClickHouse 更进一步的允许用户根据每列数据的特性选择最适合的压缩算法。如下 SQL 示例,创建 MergeTree 类型 example 表,其中:

- id 列使用的 LZ4 算法,主要用于需要快速压缩和解压缩的场景
- name 列使用的 ZSTD 算法,主要用于日志、文本、二进制数据数据,该算法在压缩效率、速度和压缩比之间有良好的平衡
- id 列使用的 LZ4 算法,主要用于需要快速压缩和解压缩的场景
- name 列使用的 ZSTD 算法,主要用于日志、文本、二进制数据数据,该算法在压缩效率、速度和压缩比之间有良好的平衡
- createTime 列使用的 Double-Delta 算法,主要用于压缩具有递增或相邻值差异较小的数据,特别适用于时间戳或计数类数据。

```SQL
Expand All @@ -129,7 +133,9 @@ CREATE TABLE example (
ORDER BY id;
```

作为一款分布式数据系统,ClickHouse 自然支持“分片”(Sharding)技术。ClickHouse 可将海量数据水平切分成多个较小的部分,并分布到多个物理节点。也就是说,只要有足够多的硬件资源,ClickHouse 就能处理数万亿条记录、PB 级别规模的数据量。根据 Yandex 内部的基准测试结果来看(图 9-9),ClickHouse 性能表现遥遥领先对手,比 Vertica(一款商业 OLAP 软件)快约 5 倍、比 Hive 快 279 倍、比 InfiniDB 快 31 倍。
作为一款分布式数据系统,ClickHouse 自然支持“分片”(Sharding)技术。

ClickHouse 将海量数据切分成多个较小的部分,并分布到多个物理节点。也就是说,只要有足够多的硬件资源,ClickHouse 就能处理数万亿条记录、PB 级别规模的数据量。根据 Yandex 内部的基准测试结果来看(图 9-9),ClickHouse 性能表现遥遥领先对手,比 Vertica(一款商业 OLAP 软件)快约 5 倍、比 Hive 快 279 倍、比 InfiniDB 快 31 倍。

:::center
![](../assets/ClickHouse-benchmark.jpeg)<br/>
Expand Down
12 changes: 6 additions & 6 deletions Observability/metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

为便于理解和使用不同类型的指标,Prometheus 定义了四种指标类型:

- **计数器**(Counter):一种只增不减的指标类型,用于记录特定事件的发生次数。常用于统计请求次数、任务完成数量、错误发生次数等。在监控 Web 服务器时,可以使用 Counter 来记录 HTTP 请求的总数,通过观察这个指标的增长趋势,能了解系统的负载情况
- **仪表盘**(Gauge):一种可以任意变化的指标,用于表示某个时刻的瞬时值。常用于监控系统的当前状态,如内存使用量、CPU 利用率、当前在线用户数等
- **直方图**(Histogram):用于统计数据在不同区间的分布情况。它会将数据划分到多个预定义的桶(bucket)中,记录每个桶内数据的数量。常用于分析请求延迟、响应时间、数据大小等分布情况。比如监控服务响应时间时,Histogram 可以将响应时间划分到不同的桶中,如 0-100ms、100-200ms 等,通过观察各个桶中的数据分布,能快速定位响应时间的集中区间和异常情况
- **计数器**(Counter):一种只增不减的指标类型,用于记录特定事件的发生次数。常用于统计请求次数、任务完成数量、错误发生次数等。在监控 Web 服务器时,可以使用 Counter 来记录 HTTP 请求的总数,通过观察这个指标的增长趋势,能了解系统的负载情况
- **仪表盘**(Gauge):一种可以任意变化的指标,用于表示某个时刻的瞬时值。常用于监控系统的当前状态,如内存使用量、CPU 利用率、当前在线用户数等
- **直方图**(Histogram):用于统计数据在不同区间的分布情况。它会将数据划分到多个预定义的桶(bucket)中,记录每个桶内数据的数量。常用于分析请求延迟、响应时间、数据大小等分布情况。比如监控服务响应时间时,Histogram 可以将响应时间划分到不同的桶中,如 0-100ms、100-200ms 等,通过观察各个桶中的数据分布,能快速定位响应时间的集中区间和异常情况
- **摘要**(Summary):和直方图类似,摘要也是用于统计数据的分布情况,但与直方图不同的是,Summary 不能提供数据在各个具体区间的详细分布情况,更侧重于单一实例(例如单个服务实例)的数据进行计算。

:::center
Expand All @@ -30,8 +30,8 @@

收集指标看似简单,但实际上复杂得多:首先,应用程序、操作系统和硬件设备的指标获取方式各不相同;其次,它们通常不会以 Prometheus 格式直接暴露。例如:

- Linux 的许多指标信息存储在 /proc 目录下,如 /proc/meminfo 提供内存信息,/proc/stat 提供 CPU 信息
- Redis 的监控数据通过执行 INFO 命令获取
- Linux 的许多指标信息存储在 /proc 目录下,如 /proc/meminfo 提供内存信息,/proc/stat 提供 CPU 信息
- Redis 的监控数据通过执行 INFO 命令获取
- 路由器等硬件设备的监控数据通常通过 SNMP 协议获取。

为了解决上述问题,Prometheus 设计了 Exporter 作为监控系统与被监控目标之间的“中介”,负责将不同来源的监控数据转换为 Prometheus 支持的格式。
Expand Down Expand Up @@ -91,7 +91,7 @@ http_request_total 5
针对时序数据特点,业界已发展出专门优化的数据库类型 —— 时序数据库(Time-Series Database,简称 TSDB)。与常规数据库(如关系型数据库或 NoSQL 数据库)相比,时序数据库在设计和用途上存在显著差异,比如:

- **数据结构**
时序数据库一般采用 LSM-Tree,这是一种专为写密集型场景设计的存储结构,其原理是将数据先写入内存,待积累一定量后批量合并并写入磁盘。因此,时序数据库在写入吞吐量方面,通常优于常规数据库(基于 B+Tree)
时序数据库一般采用 LSM-Tree,这是一种专为写密集型场景设计的存储结构,其原理是将数据先写入内存,待积累一定量后批量合并并写入磁盘。因此,时序数据库在写入吞吐量方面,通常优于常规数据库(基于 B+Tree)
- **数据保留策略**:时序数据具有明确的生命周期(监控数据只需要保留几天)。为防止存储空间无限膨胀,时序数据库通常支持自动化的数据保留策略。比如设置基于时间的保留规则,超过 7 天就会自动删除。


Expand Down
10 changes: 5 additions & 5 deletions Observability/profiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@

性能数据有多种类型,每种类型由不同的分析器(Profiler)生成,常见的分析器包括:

- **CPU 分析器**:跟踪程序中每个函数或代码块的运行时间,记录函数调用堆栈信息,生成调用图,并展示函数之间的调用关系和时间分布
- **堆分析器(Heap Profiler)**:监控程序的内存使用情况,帮助定位内存泄漏或不必要的内存分配。例如,Java 工程师通过堆分析器定位导致内存溢出的具体对象
- **GPU 分析器**:分析 GPU 的使用情况,主要用于图形密集型应用(如游戏开发),优化渲染性能
- **互斥锁分析器**:检测程序中互斥锁的竞争情况,帮助优化线程间的并发性能,减少锁争用引发的性能瓶颈
- **I/O 分析器**:评估 I/O 操作的性能,包括文件读写延迟和网络请求耗时,帮助识别数据传输瓶颈并提高效率
- **CPU 分析器**:跟踪程序中每个函数或代码块的运行时间,记录函数调用堆栈信息,生成调用图,并展示函数之间的调用关系和时间分布
- **堆分析器(Heap Profiler)**:监控程序的内存使用情况,帮助定位内存泄漏或不必要的内存分配。例如,Java 工程师通过堆分析器定位导致内存溢出的具体对象
- **GPU 分析器**:分析 GPU 的使用情况,主要用于图形密集型应用(如游戏开发),优化渲染性能
- **互斥锁分析器**:检测程序中互斥锁的竞争情况,帮助优化线程间的并发性能,减少锁争用引发的性能瓶颈
- **I/O 分析器**:评估 I/O 操作的性能,包括文件读写延迟和网络请求耗时,帮助识别数据传输瓶颈并提高效率
- **特定编程语言分析器**:例如 JVM Profiler,用于分析在 Java 虚拟机上运行的应用程序,挖掘与编程语言特性相关的性能问题。

过去,由于分析器资源消耗较高,通常仅在紧急情况下启用。随着低开销分析技术的发展,如编程语言层面的 Java Flight Recorder 和 Async Profiler 技术、操作系统层面的 systemTap 和 eBPF 技术的出现,让在生产环境进行持续性能分析(Continuous Profiling)成为可能,解决线上“疑难杂症”也变得更加容易。
Expand Down
2 changes: 1 addition & 1 deletion http/conclusion.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

本章,我们详细分析了 HTTPS 的请求过程,讲解了其中域名解析、内容压缩、SSL 层加密、网络拥塞控制等主要的环节的原理和优化操作。相信你对于构建足够快的网络服务,有了足够的认识。

总体而言,要构建“足够快”的网络服务,首先是保证域名解析不能失败,然后请求要足够快(使用 QUIC、Brotli 压缩)、足够安全(使用 TLS1.3 协议 + ECC 证书,即快又安全)、还要充分利用带宽(使用 BBR 提高网络吞吐率)。最后,技术无法解决的(长链路、弱网、海外网络),那就得花钱(CDN、边缘节点加速、建立当地数据中心)。
总结来说,要构建“足够快”的网络服务,首先是保证域名解析不能失败,然后请求要足够快(使用 QUIC、Brotli 压缩)、足够安全(使用 TLS1.3 协议 + ECC 证书,即快又安全)、还要充分利用带宽(使用 BBR 提高网络吞吐率)。最后,技术无法解决的(长链路、弱网、海外网络),那就得花钱(CDN、边缘节点加速、建立当地数据中心)。
Loading

0 comments on commit 612257f

Please sign in to comment.