├── .github
└── workflows
│ └── deploy.yml
├── .gitignore
├── .vuepress
├── client.js
├── config.js
├── layouts
│ └── layout.vue
├── public
│ ├── assets
│ │ └── favicon.ico
│ └── icon.png
└── styles
│ └── index.scss
├── Observability
├── Observability-vs-Monitoring.md
├── OpenTelemetry.md
├── What-is-Observability.md
├── conclusion.md
├── dumps.md
├── logging.md
├── metrics.md
├── profiles.md
├── signals.md
├── summary.md
└── tracing.md
├── README.md
├── ServiceMesh
├── MicroService-history.md
├── The-future-of-ServiceMesh.md
├── What-is-ServiceMesh.md
├── conclusion.md
├── control-plane.md
├── data-plane.md
├── overview.md
└── summary.md
├── about.md
├── application-centric
├── Controller.md
├── Helm.md
├── Kustomize.md
├── OAM.md
├── Operator.md
├── app-model.md
├── application-centric.md
├── conclusion.md
└── summary.md
├── architecture
├── Immutable.md
├── MicroService.md
├── ServiceMesh.md
├── arc.md
├── architect.md
├── background.md
├── cloud-native-tech.md
├── conclusion.md
├── container.md
├── declarative-api.md
├── define-cloud-native.md
├── devops.md
├── history.md
├── summary.md
└── target.md
├── assets
├── 2021-02-secrets-management.svg
├── 6-b.png
├── ABA.svg
├── Ambient-Mesh-2.png
├── Ambient-Mesh.png
├── Ambient-Mesh.svg
├── BASE.svg
├── Borg.jpeg
├── CA.svg
├── CI.png
├── CNI.png
├── CNI.webp
├── CRD.webp
├── CSI.png
├── ClickHouse-benchmark.jpeg
├── Cluster-AutoScaler.png
├── Dapper-trace-span.png
├── Device-plugin.webp
├── DevicePlugin.svg
├── ELK.png
├── Flannel-UDP-TUN.webp
├── Flannel-UDP.webp
├── HPA.svg
├── Immutable.png
├── JuiceFS.png
├── Monitoring-vs-Observability.png
├── Monolith-vs-MicroService.png
├── Netfilter-packet-flow.svg
├── OAM-how-it-works.png
├── OAM.jpg
├── OCSP-Stapling.png
├── Pinpoint.png
├── RDMA.png
├── Replicated-state-machine.webp
├── RoCE_Header_format.png
├── ServiceMesh-summary.png
├── SoftwareEatingTheWorld.jpg
├── SpringCloud.webp
├── TCC.svg
├── TCP.svg
├── TriggerFlow.svg
├── VXLAN.png
├── Volcano-arch.png
├── XDP.svg
├── active_and_passive_arch.png
├── agile-model.png
├── agile-word.png
├── ambient-layers.png
├── ambient-mesh-arch.png
├── application-centric.png
├── arc-1.svg
├── argocd-demo.png
├── argocd.png
├── argocd_architecture.png
├── artifact-hub.jpg
├── balance-summary.png
├── balancer-4.svg
├── balancer-edge-proxy.svg
├── balancer-ha-2.svg
├── balancer-ha.svg
├── balancer-sdk.svg
├── balancer-sidecar.svg
├── balancer.svg
├── balancer4-NAT.svg
├── balancer4-dsr.svg
├── balancer4-tunnel.svg
├── balancer4.svg
├── balancer7.svg
├── basic-paxos.png
├── bbr-2.png
├── bbr-cc.png
├── bbr-status.png
├── bbr.png
├── bench_tcp_crr_32_processes.png
├── bench_tcp_crr_32_processes_cpu (1).png
├── bench_tcp_crr_32_processes_cpu.png
├── bench_tcp_stream_32_streams_cpu.png
├── borg-arch.png
├── bridge-call-iptables.svg
├── brotli.jpeg
├── brotli.png
├── byzantine-1.svg
├── byzantine-2.svg
├── byzantine-3.svg
├── byzantine-4.svg
├── byzantine-5.svg
├── byzantine-6.svg
├── calico-bgp.svg
├── cap-theorem.png
├── cc.png
├── cd.png
├── chroot.png
├── cicd-push.png
├── cicd-tools.svg
├── cicd.png
├── cilium-istio-benchmark.webp
├── cilium.svg
├── cloud-history-1.svg
├── cloud-history-2.png
├── cloud-history-2.svg
├── cloud-history-3.png
├── cloud-history-3.svg
├── cloud-native-goals-2.png
├── cloud-native-goals.png
├── cloud-native.png
├── cloud-summary.png
├── cloud.svg
├── cloudflare-dns.png
├── cncf-cloud-native.svg
├── cncf-observability.png
├── cni-plugin.png
├── cni0.svg
├── column-database.png
├── compress.png
├── conntrack-nat.png
├── conntrack-nat.svg
├── conntrack.png
├── consensus-summary.png
├── consensus.png
├── container-2.jpeg
├── container-summary.png
├── containerd-arch.png
├── containerd-built-in-plugin.png
├── containerd-cri.png
├── cri-arc.png
├── cri-architecture.png
├── csi-k8s.png
├── custom-chain.png
├── dapper-log.png
├── declarative.svg
├── definition-cap.png
├── deployment-controller.png
├── device-plugin.png
├── devops-2.jpg
├── devops-wall.png
├── devops.jpeg
├── distributed-transaction.png
├── dns-1.png
├── dns-2.png
├── dns-example.png
├── dns-tree.webp
├── docker-arc.png
├── docker-file-system.png
├── docker-image.png
├── docker.png
├── dockerfile.png
├── dpdk.png
├── dpvs-performance.png
├── dragonfly.png
├── dsa.png
├── ebpf-go.webp
├── ebpf.webp
├── ecc.png
├── envoy-resource.png
├── es-vs-clickhouse.png
├── facebook-404-error.jpeg
├── flagger.png
├── flannel-route.svg
├── flannel-vxlan.svg
├── four-metrics-type.png
├── github-tekton.png
├── gitops-workflow.webp
├── global-lb.png
├── global-load-balancer.svg
├── grafana-dashboard-english.png
├── helm.webp
├── how_mtls_works-what_is_mutual_tls.png
├── how_tls_works.png
├── http-process.png
├── http-quic.png
├── http-summary.png
├── http3.png
├── httpdns.png
├── https-1.png
├── https-2.png
├── https-3.png
├── https-4.png
├── https-5.png
├── hybrid-cloud.svg
├── id-service.png
├── infra-container.svg
├── ip.svg
├── iptables-chain.png
├── iptables-vs-ipvs.png
├── iptables.png
├── istio-iptables.svg
├── k8s-1.png
├── k8s-arch.svg
├── k8s-ca.svg
├── k8s-chain.png
├── k8s-cri-o.png
├── k8s-cri.png
├── k8s-metadata.jpeg
├── k8s-resource.svg
├── k8s-runtime-v1.svg
├── k8s-runtime-v2.png
├── k8s-runtime-v3.png
├── k8s-runtime-v4.svg
├── k8s-selector.png
├── k8s-service.png
├── k8s-service.svg
├── k8s-sidecar.png
├── k8s-volume.svg
├── kaniko.png
├── kata-container-diff.png
├── kata-container.jpeg
├── kata-container.jpg
├── kata-container.png
├── keda-arch.png
├── kube-scheduler.png
├── kube-scheduler.svg
├── kubelet.png
├── kubernetes-container.png
├── kubernetes_operator.webp
├── kubevela.jpg
├── l4-connection-v2.svg
├── l4-connection.png
├── l4-connection.svg
├── l7-lb.png
├── l7-lb.webp
├── label.png
├── label2.png
├── landscape.png
├── latencies_p50.svg
├── latency-200rps.png
├── lb-via-client-lib.webp
├── lb-via-sidecar.webp
├── linkerd-control-plane.png
├── linkerd-envoy.png
├── linkerd-resource.png
├── linux-bridge.svg
├── linux-namespace.svg
├── linux-summary.png
├── linux-veth.svg
├── linux-vxlan.svg
├── loadbalancer.png
├── lock.png
├── log.png
├── logging.png
├── loki-arch.png
├── loki-arch.svg
├── loki-dashboard.jpeg
├── loki_architecture_components.svg
├── loud-summary.png
├── lua-cpu-flame-graph.webp
├── lvs-ha.svg
├── macvlan-veth.svg
├── macvlan.png
├── macvlan.svg
├── mesh3.png
├── mesos-arch.jpeg
├── micro-service-1.png
├── micro-service-2.png
├── monitoring.png
├── multi_paxos.png
├── multus-pod-image.svg
├── nat.png
├── netfilter-hook.svg
├── netfilter-k8s.svg
├── network-lb-overview.png
├── network-namespace.svg
├── network-summary.png
├── networking.svg
├── nginx-conf.png
├── nydus-performance.png
├── nydus.png
├── oam_model.png
├── observability-knowns.png
├── observability.jpg
├── observability.png
├── opentracing-vs-opencensus.jpg
├── operatorhub.io.png
├── otel-diagram.svg
├── overfs.jpeg
├── overlay-network.png
├── overlay.jpeg
├── overlay.png
├── overlay.svg
├── overlay_constructs.webp
├── paxos-conflict-2.png
├── paxos-conflict3.png
├── paxos-consensus.svg
├── paxos-liveness.png
├── paxos-p1.png
├── paxos-p2.png
├── paxos-p3.png
├── paxos-p4.png
├── paxos.png
├── paxos.svg
├── paxos_2pc_choice.png
├── paxos_conflict_choices.png
├── paxos_split_votes.png
├── pivotal-cloud-native-update.svg
├── pivotal-cloud-native.svg
├── pod.svg
├── ppt4.jpg
├── prometheus-arch.png
├── prometheus-exporter.png
├── prometheus-storage.jpeg
├── protobuf_message.svg
├── proxyless.svg
├── pvc-flow.png
├── qos.webp
├── qrcode-v2.png
├── quic-1.png
├── quic-3.png
├── quic-connection.png
├── quic-handshake.png
├── quic-head-block.png
├── quorum-base.png
├── raft-ConfChange.png
├── raft-append-entries.svg
├── raft-election.svg
├── raft-log-commit.png
├── raft-log-fix-action.svg
├── raft-log-fix.svg
├── raft-log.svg
├── raft-single-server.png
├── raft-single-server.svg
├── raft-state-machine.png
├── raft-term.svg
├── requests-limits.png
├── rootfs-1.jpeg
├── row-database.png
├── runtime.png
├── saga.svg
├── scheduling-framework-extensions.png
├── scheduling-framework-extensions.svg
├── service-mesh-2.png
├── service-mesh-3.png
├── service-mesh-4.png
├── service-mesh-arc.svg
├── service-mesh-kernel.jpg
├── service-mesh-overview.png
├── service-mesh-tcp-1.png
├── service-mesh-tcp.png
├── service-mesh.png
├── servicemesh-sidecar.png
├── servicemesh.png
├── sidecar-example.jpg
├── sidecar.svg
├── sidecarless.png
├── sidecarless.svg
├── skywalking-ui.jpeg
├── ssl-domain-info.png
├── ssl-test.png
├── star-history-20231218.png
├── swarm-diagram.webp
├── tcp_disconnect.svg
├── tekton-dashboard-ui.jpeg
├── tls1.2.png
├── tls1.3.png
├── tracing.png
├── tsdb.svg
├── tun.svg
├── types-of-encryption-asymmetric-encryption.png
├── types-of-encryption-symmetric-encryption.png
├── types-of-mounts-volume.webp
├── uber-microservice.png
├── veth.svg
├── vlan-router.svg
├── vlan-sub-interface.svg
├── volume-list.png
├── volume.svg
├── vxlan-data.png
├── vxlan-router.svg
├── vxlan_header.png
├── waterfall-model.svg
├── what-is-koordinator.svg
├── what-is-kubevela.jpg
├── www.thebyte.com.cn_.png
├── xaas.svg
└── xdp.png
├── balance
├── balance-features.md
├── balance-topology.md
├── balance.md
├── balance4.md
├── balance7.md
├── conclusion.md
├── global-load-balancer.md
└── summary.md
├── consensus
├── Basic-Paxos.md
├── Paxos-history.md
├── Paxos.md
├── Replicated-State-Machine.md
├── conclusion.md
├── consensus.md
├── raft-ConfChange.md
├── raft-leader-election.md
├── raft-log-replication.md
├── raft.md
└── summary.md
├── container
├── CRI.md
├── Extended-Resource.md
├── Resource-scheduling.md
├── auto-scaling.md
├── borg-omega-k8s.md
├── conclusion.md
├── container-network.md
├── image.md
├── kube-scheduler.md
├── orchestration.md
├── resource.md
├── storage.md
└── summary.md
├── distributed-transaction
├── ACID.md
├── BASE.md
├── CAP.md
├── Saga.md
├── TCC.md
├── conclusion.md
├── idempotent.md
├── summary.md
└── transaction.md
├── http
├── Edge-Acceleration.md
├── compress.md
├── conclusion.md
├── congestion-control.md
├── dns-ha.md
├── dns.md
├── http-dns.md
├── https-latency.md
├── https-summary.md
├── https.md
├── latency.md
├── quic.md
├── ssl.md
└── summary.md
├── intro.md
├── network
├── DPDK.md
├── RDMA.md
├── XDP.md
├── conclusion.md
├── conntrack.md
├── iptables.md
├── kernel-bypass.md
├── linux-bridge.md
├── linux-kernel-networking.md
├── linux-vritual-net.md
├── netfilter.md
├── network-layer.md
├── network-namespace.md
├── networking.md
├── summary.md
├── tuntap.md
├── virtual-nic.md
└── vxlan.md
├── noun.md
├── package.json
└── review.md
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Build app and deploy
2 | on:
3 | push:
4 | branches:
5 | - main
6 | jobs:
7 | build:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: Checkout
11 | uses: actions/checkout@v4
12 | - name: use Node.js 20.0.0
13 | uses: actions/setup-node@v4
14 | with:
15 | node-version: 20
16 | - name: Install and Build
17 | run: |
18 | npm cache clean --force
19 | npm install
20 | npm run build
21 | # 部署到阿里云
22 | - name: Deploy to Aliyun
23 | uses: easingthemes/ssh-deploy@v4.1.8
24 | env:
25 | SSH_PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
26 |
27 | ARGS: "-rlgoDzvc -i"
28 | SOURCE: ".vuepress/dist/"
29 | REMOTE_HOST: "110.40.229.45"
30 | REMOTE_USER: "root"
31 | TARGET: "/home/www/thebyte.com.cn"
32 | SCRIPT_BEFORE: |
33 | whoami
34 | ls -al
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .temp
3 | .cache
4 | yarn.lock
5 | .DS_store
6 | # Node rules:
7 | ## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
8 | .grunt
9 | package-lock.json
10 | yarn-error.log
11 | node_modules
12 | yarn.lock
13 |
14 | dist
15 |
16 | # eBook build output
17 | *.epub
18 | *.mobi
19 | *.pdf
20 | .cache
21 | chrome
22 |
23 | .vuepress
--------------------------------------------------------------------------------
/.vuepress/client.js:
--------------------------------------------------------------------------------
1 | import { defineClientConfig } from '@vuepress/client'
2 | import Layout from './layouts/layout.vue'
3 |
4 | export default defineClientConfig({
5 | enhance ({ router }) {
6 |
7 | },
8 | layouts: {
9 | Layout
10 | }
11 | })
--------------------------------------------------------------------------------
/.vuepress/layouts/layout.vue:
--------------------------------------------------------------------------------
1 |
2 |
19 |
16 | 图 9-1 可观测性帮助工程师解决未知的未知(Unknown Unknowns)
17 | :::
18 |
19 | X 轴的右侧(Known Knows 和 Known Unknowns)表示确定性的已知和未知,图中给出了相应的例子。这类信息通常是系统上线前就能预见,并能够监控的基础性、普适性事实(如 CPU Load、内存、TPS、QPS 等指标)。传统的监控系统大部分围绕这些确定的因素展开。
20 |
21 | 但是很多情况下,上述信息很难全面描述和衡量系统的状态。比如坐标的左上角的 Unknown Knowns(未知的已知,通俗理解为假设),举个例子,通常会引入限流策略来保证服务可用性。假设请求量突然异常暴增,限流策略牺牲小部分用户、保证绝大部分用户的体验。但注意,这里的“假设”(请求量突然暴增)并未实际发生。因此,平常情况下的监控看不出任何异常。
22 |
23 | 但如果请求量突然暴增了,同时那些“假设”又未经过验证(如限流逻辑写错了),就会导致我们碰见最不愿见到的情况 —— Unknown Unknowns(未知的未知,毫无征兆且难以理解)。
24 |
25 | 经验丰富(翻了无数次车)的工程师根据以往经验,逐步缩小 Unknown Unknowns 的排查范围,从而缩短故障修复时间。但更合理的做法是,根据系统的细微输出(如 metrics、logs、traces,也就是遥测数据),以低门槛且直观的方式(如监控大盘、链路追踪拓扑等)描绘出系统的全面状态。如此,当发生 Unknown Unkowns 情况时,才能具象化的一步步定位到问题的根因。
26 |
27 | [^1]: 参见 https://blog.sciencenet.cn/blog-829-1271882.html
28 |
--------------------------------------------------------------------------------
/Observability/OpenTelemetry.md:
--------------------------------------------------------------------------------
1 | # 9.4 可观测标准的演进
2 |
3 | Dapper 论文发布后,市场上涌现出大量追踪系统,如 Jaeger、Pinpoint、Zipkin 等。这些系统都基于 Dapper 论文实现,功能上无本质差异,但实现方式和技术栈不同,导致它们难以兼容或协同使用。
4 |
5 | 为解决追踪系统各自为政的乱象,一些老牌应用性能监控(APM)厂商(如 Uber、LightStep 和 Red Hat)联合定义了一套跨语言的、平台无关分布式追踪标准协议 —— OpenTracing。
6 |
7 | 开发者只需按照 OpenTracing 规范实现追踪接口,便可灵活替换、组合探针、存储和界面组件。2016 年,CNCF 将 OpenTracing 收录为其第三个项目,前两个分别是大名鼎鼎的 Kubernetes 和 Prometheus。这一举措标志着 OpenTracing 作为分布式系统可观测性领域的标准之一,获得了业界的广泛认可。
8 |
9 | OpenTracing 推出后不久,Google 和微软联合推出了 OpenCensus 项目。OpenCensus 起初是 Google 内部的监控工具,开源的目的并非与 OpenTracing 竞争,而是希望为分布式系统提供一个统一的、跨语言的、开箱即用的可观测性框架,不仅仅处理链路追踪(tracing)、还要具备处理指标(metrics)的能力。
10 |
11 | 虽说 OpenTracing 和 OpenCensus 推动了可观测性系统的发展,但它们作为协议标准,彼此之间的竞争和分裂不可避免地消耗了大量社区资源。对于普通开发者而言,一边是老牌 APM 厂商,另一边是拥有强大影响力的 Google 和微软。选择困难症发作时,一个新的设想不断被讨论:“能否有一个标准方案,同时支持指标、追踪和日志等各类遥测数据?”。
12 |
13 | 2019 年,OpenTracing 和 OpenCensus 的维护者决定将两个项目整合在一起,形成了现在的 OpenTelemetry 项目。OpenTelemetry 做的事情是,提供各类遥测数据统一采集解决方案。
14 |
15 | 如图 9-17 所示,集成了 OpenTelemetry 的可观测系统:
16 |
17 | - 应用程序只需要一种 SDK 就可以实现所有类型遥测数据的生产;
18 | - 集群只需要部署一个 OpenTelemetry Collector 便可以采集所有的遥测数据。
19 |
20 | :::center
21 | 
22 | 图 9-17 集成 OpenTelemetry 的可观测架构 [图片来源](https://opentelemetry.io/docs/)
23 | :::
24 |
25 | 至于遥测数据采集后如何存储、展示、使用,OpenTelemetry 并不涉及。你可以使用 Prometheus + Grafana 做指标的存储和展示,也可以使用 Jaeger 做链路追踪的存储和展示。这使得 OpenTelemetry 既不会因动了“数据的蛋糕”,引起生态抵制,也保存了精力,专注实现兼容“所有的语言、所有的系统”的“遥测数据采集器”(OpenTelemetry Collector)。
26 |
27 | 自 2019 年发布,OpenTelemetry 便得到了社区的广泛支持。绝大部分云服务商,如 AWS、Google Cloud、Azure、阿里云等均已支持和推广 OpenTelemetry,各种第三方工具(如 Jaeger、Prometheus、Zipkin)也逐步集成 OpenTelemetry,共同构建了丰富的可观测性生态系统。
--------------------------------------------------------------------------------
/Observability/What-is-Observability.md:
--------------------------------------------------------------------------------
1 | # 9.1 什么是可观测性
2 |
3 | 什么是可观测性?观测的又是什么?
4 |
5 | Google Cloud 在介绍可观测标准项目 OpenTelemetry 时提到一个概念 —— “遥测数据”(telemetry data)[^1]。
6 |
7 | :::tip 遥测数据
8 |
9 | 遥测数据(telemetry data)是指采样和汇总有关软件系统性能和行为的数据,这些数据(接口的响应时间、请求错误率、服务资源消耗等)用于监控和了解系统的当前状态。
10 | :::
11 |
12 | “遥测数据”看起来陌生,但你肯定无意间听过。观看火箭发射的直播时,你应该听到过类似的指令:“东风光学 USB 雷达跟踪正常,遥测信号正常” 。随着火箭升空,直播画面还会特意切换到一个看起来“高大上”仪表控制台。
13 |
14 | 实际上,软件领域的观测与上述火箭发射系统相似,都是通过全面收集系统运行数据(遥测数据),以了解内部状态。所以说,可观测性是指系统的内部状态能够通过外部输出(如日志、指标、追踪等)来进行观察和理解的能力。换句话说,系统的可观测性使得我们能够从系统的外部获取足够的信息,以便分析和解决可能存在的问题,预测系统行为,或者优化系统性能。
15 | [^1]: 参见 https://cloud.google.com/learn/what-is-opentelemetry
16 |
--------------------------------------------------------------------------------
/Observability/conclusion.md:
--------------------------------------------------------------------------------
1 | # 9.5 小结
2 |
3 | 通过本章的内容,相信你已经理解了什么是可观测性?简单来说,就是通过系统的外部输出推断其内部状态的能力。
4 |
5 | 系统的外部输出称为“遥测数据”,主要包括日志、指标和追踪数据。建立良好的可观测性机制,实质上是对这些数据进行统一收集、关联和分析。这其中还有两个关键:首先,要低开销。可观测性的一大目的就是发现性能问题,因此不应对业务造成明显的性能负担。对于对延迟敏感的业务,任何微小的性能损耗都可能产生明显的影响。其次,业务透明性至关重要。观测能力通常是在运维阶段加入的,因此应以非侵入或最小侵入的方式实现,尽量避免对业务开发造成干扰。
6 |
7 |
--------------------------------------------------------------------------------
/Observability/dumps.md:
--------------------------------------------------------------------------------
1 | # 9.3.5 核心转储
2 |
3 | 核心转储(Core dump)中的 “core” 代表程序的关键运行状态,“dump” 的意思是导出。
4 |
5 | 核心转储历史悠久,很早就在各类 Unix 系统中出现。在任何安装了《Linux man 手册》的 Linux 发行版中,都可以运行 man core 命令查阅相关信息。
6 |
7 | ```bash
8 | $ man core
9 | ...
10 | A small number of signals which cause abnormal termination of a process
11 | also cause a record of the process's in-core state to be written to disk
12 | for later examination by one of the available debuggers. (See
13 | sigaction(2).)
14 | ...
15 | ```
16 |
17 | 上面的大致意思是,当程序异常终止时,Linux 系统会将程序的关键运行状态(如程序计数器、内存映像、堆栈跟踪等)导出到一个“核心文件”(core file)中。工程师通过调试器(如 gdb)打开核心文件,查看程序崩溃时的运行状态,从而帮助定位问题。
18 |
19 | :::tip 注意
20 | 复杂应用程序崩溃时,可能会生成几十 GB 大小的核心文件。默认情况下,Linux 系统会限制核心文件的大小。如果你想解除限制,可通过命令 ulimit -c unlimited,告诉操作系统不要限制核心文件的大小。
21 | :::
22 |
23 | 值得一提的是,虽然 CNCF 发布的可观测性白皮书仅提到了 core dump。实际上,重要的 dumps 还有 Heap dump(Java 堆栈在特定时刻的快照)、Thread dump(特定时刻的 Java 线程快照)和 Memory dump(内存快照)等等。
24 |
25 | 最后,尽管 CNCF 将 dumps 纳入了可观测性体系,但仍有许多技术难题,如容器配置与操作系统全局配置的冲突、数据持久化的挑战(Pod 重启前将数 Gb 的 core 文件写入持久卷)等等,导致处理 dumps 数据还得依靠传统手段。
--------------------------------------------------------------------------------
/Observability/profiles.md:
--------------------------------------------------------------------------------
1 | # 9.3.4 性能剖析
2 |
3 | 可观测性领域的性能剖析(Profiling)的目标是分析运行中的应用,生成详细的性能数据(Profiles),帮助工程师全面了解应用的运行行为和资源使用情况,从而识别代码中的性能瓶颈。
4 |
5 | 性能数据通常以火焰图或堆栈图的形式呈现,分析这些数据是从“是什么”到“为什么”过程中的关键环节。例如,通过链路追踪识别延迟源(是什么),然后根据火焰图进一步分析,定位到具体的代码行(为什么)。2021 年,某网站发生崩溃事件,工程师通过分析火焰图发现 Lua 代码存在异常,最终定位到问题源头。[^1]。
6 |
7 | :::center
8 | 
9 | 图 9-16 Lua 代码的 CPU 火焰图(由于函数调用按层叠加,火焰图呈现出类似火焰的形状)
10 | :::
11 |
12 | :::tip 火焰图分析说明
13 |
14 | - 纵轴:表示函数调用的堆栈深度(或层级)。纵向越高表示调用链越深,底部通常是程序的入口函数(如 main 函数),上层是被下层函数调用的函数。
15 | - 横轴:表示函数在特定时间段内所占用的 CPU 时间或内存空间,条形的宽度越大,表示该函数消耗的时间或资源越多。
16 |
17 | 分析火焰图的关键是观察横向条形的宽度,宽度越大,函数占用的时间越多。如果某个函数的条形图出现“平顶”现象,表示该函数的执行时间过长,可能成为性能瓶颈。
18 | :::
19 |
20 | 性能数据有多种类型,每种类型由不同的分析器(Profiler)生成,常见的分析器包括:
21 |
22 | - **CPU 分析器**:跟踪程序中每个函数或代码块的运行时间,记录函数调用堆栈信息,生成调用图,并展示函数之间的调用关系和时间分布;
23 | - **堆分析器(Heap Profiler)**:监控程序的内存使用情况,帮助定位内存泄漏或不必要的内存分配。例如,Java 工程师通过堆分析器定位导致内存溢出的具体对象;
24 | - **GPU 分析器**:分析 GPU 的使用情况,主要用于图形密集型应用(如游戏开发),优化渲染性能;
25 | - **互斥锁分析器**:检测程序中互斥锁的竞争情况,帮助优化线程间的并发性能,减少锁争用引发的性能瓶颈;
26 | - **I/O 分析器**:评估 I/O 操作的性能,包括文件读写延迟和网络请求耗时,帮助识别数据传输瓶颈并提高效率;
27 | - **特定编程语言分析器**:例如 JVM Profiler,用于分析在 Java 虚拟机上运行的应用程序,挖掘与编程语言特性相关的性能问题。
28 |
29 | 过去,由于分析器资源消耗较高,通常仅在紧急情况下启用。随着低开销分析技术的发展,如编程语言层面的 Java Flight Recorder 和 Async Profiler 技术、操作系统层面的 systemTap 和 eBPF 技术的出现,让在生产环境进行持续性能分析(Continuous Profiling)成为可能,解决线上“疑难杂症”也变得更加容易。
30 |
31 | [^1]: 参见《2021.07.13 我们是这样崩的》https://www.bilibili.com/read/cv17521097/
32 |
33 |
--------------------------------------------------------------------------------
/Observability/signals.md:
--------------------------------------------------------------------------------
1 | # 9.3 遥测数据的分类与处理
2 |
3 | 业界将系统输出的数据总结为三种独立的类型,它们的含义与区别如下:
4 |
5 | - **指标**(metric):量化系统性能和状态的“数据点”,每个数据点包含度量对象(如接口请求数)、度量值(如 100 次/秒)和发生的时间,多个时间上连续的数据点便可以分析系统性能的趋势和变化规律。指标是发现问题的起点,例如你半夜收到一条告警:“12 点 22 分,接口请求成功率下降到 10%”,这表明系统出现了问题。接着,你挣扎起床,分析链路追踪和日志数据,找到问题的根本原因并进行修复。
6 |
7 | - **日志**(log):系统运行过程中,记录离散事件的文本数据。每条日志详细描述了事件操作对象、操作结果、操作时间等信息。例如下面的日志示例,包含了时间、日志级别(ERROR)以及事件描述。
8 | ```bash
9 | [2024-12-27 14:35:22] ERROR: Failed to connect to database. Retry attempts exceeded.
10 | ```
11 | 日志为问题诊断提供了精准的上下文信息,与指标形成互补。当系统故障时,“指标”告诉你应用程序出现了问题,“日志”则解释了问题出现的原因。
12 |
13 | - **链路追踪**(trace):记录请求在多个服务之间的“调用链路”(Trace),以“追踪树”(Trace Tree)的形式呈现请求的“调用”(span)、耗时分布等信息。
14 |
15 | ```bash
16 | // 追踪树
17 | Trace ID: 12345
18 | └── Span ID: 1 - API Gateway (Duration: 50ms)
19 | └── Span ID: 2 - User Service (Duration: 30ms)
20 | └── Span ID: 3 - Database Service (Duration: 20ms)
21 | ```
22 |
23 | 上述 3 类数据各自侧重不同,但并非孤立存在,它们之间有着天然的交集与互补。比如指标监控(告警)帮助发现问题,日志和链路追踪则帮助定位根本原因。这三者之间的关系如图 9-2 的韦恩图所示。
24 |
25 | :::center
26 | 
27 | 图 9-2 指标、链路追踪、日志三者之间的关系 [图片来源](https://peter.bourgon.org/blog/2017/02/21/metrics-tracing-and-logging.html)
28 | :::
29 |
30 |
31 | 2021 年,CNCF 发布了可观测性白皮书[^1],里面新增了性能剖析(Profiling)和核心转储(Core dump)2 种数据类型。接下来,笔者将详细介绍这 5 类遥测数据的采集、存储和分析原理。
32 |
33 | [^1]: 参见 https://github.com/cncf/tag-observability/blob/main/whitepaper.md
--------------------------------------------------------------------------------
/Observability/summary.md:
--------------------------------------------------------------------------------
1 | # 第九章:系统可观测性
2 | :::tip
3 | given enough eyeballs, all bugs are shallow.
4 |
5 | 足够多的眼睛,就可让所有问题浮现。
6 |
7 | :::right
8 | —— by Linus Torvalds
9 | :::
10 |
11 | 随着系统规模扩大、组件复杂化以及服务间依赖关系的增加,确保系统稳定性已超出绝大多数 IT 团队的能力极限。
12 |
13 | 复杂性失控问题在工业领域同样出现过。19 世纪末起,电气工程的细分领域迅速发展,尤其是 20 世纪 50 年代的航空领域,研发效率要求越来越高、运行环境越来越多样化,系统日益复杂对稳定性提出了巨大挑战。在这一背景下,匈牙利裔工程师 Rudolf Emil Kálmán 提出了“可观测性”概念,其理念的核心是“通过分析系统向外部输出的信号,判断工作状态并定位缺陷的根因”。
14 |
15 | 借鉴电气系统的观测理念,我们也可以通过系统输出各类信息,实现软件系统的可观测。2018 年,CNCF 率先将“可观测性”概念引入 IT 领域,强调它是云原生时代软件的必备能力!从生产所需到概念发声,加之 Google 在内的众多大厂一拥而上,“可观测性”逐渐取代“监控”,成为云原生领域最热门的话题之一。
16 |
17 | 本章内容安排如图 9-0 所示。
18 | :::center
19 | 
20 | 图 9-0 本章内容导读
21 | :::
--------------------------------------------------------------------------------
/Observability/tracing.md:
--------------------------------------------------------------------------------
1 | # 9.3.3 分布式链路追踪
2 |
3 | Uber 是实施微服务架构的先驱,他们曾经撰写博客介绍过它们的打车系统,该系统约由 2,200 个相互依赖的微服务组成。引用资料中的配图,直观感受铺面而来的复杂性。
4 | :::center
5 | 
6 | 图 9-10 Uber 使用 Jaeger 生成的追踪链路拓扑 [图片来源](https://www.uber.com/en-IN/blog/microservice-architecture/)
7 | :::
8 |
9 | 上述微服务由不同团队使用不同编程语言开发,部署在数千台服务器上,横跨多个数据中心。这种规模使系统行为变得难以全面掌控,且故障排查路径异常复杂。因此,理解复杂系统的行为状态,并析性能问题的需求显得尤为迫切。
10 |
11 | 2010 年 4 月,Google 工程师发表了论文《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》[1],论文总结了他们治理分布式系统的经验,并详细介绍了 Google 内部分布式链路追踪系统 Dapper 的架构设计和实现方法。
12 |
13 | Dapper 论文的发布,让治理复杂分布式系统迎来了转机,链路追踪技术开始在业内备受推崇!
14 |
15 | ## 1. 链路追踪的基本原理
16 |
17 | 如今的链路追踪系统大多以 Dapper 为原型设计,因为它们也统一继承了 Dapper 的核心概念:
18 |
19 | - **追踪(trace)**:Trace 表示一次完整的分布式请求生命周期,它是一个全局上下文,包含了整个调用链所有经过的服务节点和调用路径。例如,用户发起一个请求,从前端服务到后端数据库的多次跨服务调用构成一个 Trace。
20 | - **跨度(Span)**:Span 是 Trace 中的一个基本单元,表示一次具体的操作或调用。一个 Trace 由多个 Span 组成,按时间和因果关系连接在一起。Span 内有描述操作的名称 span name、记录操作的开始时间和持续时间、Trace ID、当前 Span ID、父 Span ID(构建调用层级关系)等信息。
21 |
22 | 总结链路追踪系统的基本原理是,为每个操作或调用记录一个跨度,一个请求内的所有跨度共享一个 trace id。通过 trace id,便可重建分布式系统服务间调用的因果关系。换言之,链路追踪(Trace)是由若干具有顺序、层级关系的跨度组成一棵追踪树(Trace Tree),如图 9-1 所示。
23 |
24 | :::center
25 | 
26 | 图 9-11 由不同跨度组成的追踪树
27 | :::
28 |
29 | 从链路追踪系统的实现来看,核心是在服务调用过程中收集 trace 和 span 信息,并汇总生成追踪树结构。接下来,笔者将从数据采集、数据展示(分析)两个方面展开,解析主流链路追踪系统的设计原理。
30 |
31 | ## 2. 数据采集
32 |
33 | 目前,追踪系统的主流实现有三种,具体如下:
34 |
35 | - **基于日志的追踪**(Log-Based Tracing):直接将 Trace、Span 等信息输出到应用日志中,然后采集所有节点的日志汇聚到一起,再根据全局日志重建完整的调用链拓扑。这种方式的优点是没有网络开销、应用侵入性小、性能影响低;但其缺点是,业务调用与日志归集不是同时完成的,有可能业务调用已经结束,但日志归集不及时,导致追踪失真。
36 |
37 | 根据图 9-13,总结 Dapper 基于日志实现的追踪如下:
38 |
39 | 1. 将 Span 数据写入本地日志文件。
40 | 2. Dapper 守护进程(Dapper Daemon)和采集器(Dapper Collectors)从主机节点读取日志。
41 | 3. 将日志写入 Bigtable 仓库,每行代表一个 Trace,每列代表一个 Span。
42 | :::center
43 | 
44 | 图 9-13 基于日志实现的追踪
45 | :::
46 |
47 | - **基于服务的追踪**(Service-Based Tracing):通过某些手段给目标应用注入追踪探针(Probe),然后通过探针收集服务调用信息并发送给链路追踪系统。探针通常被视为一个嵌入目标服务的小型微服务系统,具备服务注册、心跳检测等功能,并使用专用的协议将监控到的调用信息通过独立的 HTTP 或 RPC 请求发送给追踪系统。
48 |
49 | 以 SkyWalking 的 Java 追踪探针为例,它实现的原理是将需要注入的类文件(追踪逻辑代码)转换成字节码,然后通过拦截器注入到正在运行的应用程序中。比起基于日志实现的追踪,基于服务的追踪在资源消耗和侵入性(但对业务工程师基本无感知)上有所增加,但其精确性和稳定性更高。现在,基于服务的追踪是目前最为常见的实现方式,被 Zipkin、Pinpoint、SkyWalking 等主流链路追踪系统广泛采用。
50 |
51 | - **基于边车代理的追踪**(Sidecar-Based Tracing):这是服务网格中的专属方案,基于边车代理的模式无需修改业务代码,也没有额外的开销,是最理想的分布式追踪模型。总结它的特点如下:
52 | - 对应用完全透明:有自己独立数据通道,追踪数据通过控制平面上报,不会有任何依赖或干扰;
53 | - 与编程语言无关:无论应用采用什么编程语言,只要它通过网络(如 HTTP 或 gRPC)访问服务,就可以被追踪到。
54 |
55 | 目前,市场占有率最高的边车代理 Envoy 就提供了链路追踪数据采集功能,但 Envoy 没有自己的界面端和存储端,需要配合专门的 UI 与存储系统来使用。不过,Zipkin、SkyWalking、Jaeger 和 LightStep Tracing 等等系统都能够接收来自 Envoy 的链路追踪数据,充当其界面和存储端。
56 |
57 | ## 3. 数据展示
58 |
59 | 追踪数据通常以两种形式呈现:调用链路图和调用拓扑图,具体如下:
60 |
61 | - **调用链路图**:主要突出调用的深度、每一次调用的延迟。调用链路图通常用来定位故障。例如,当某次请求失败时,通过调用链路图可以追踪调用经过的各个环节,定位是哪一层调用失败。
62 | :::center
63 | 
64 | 图 9-14 Skywalking 的调用链路图
65 | :::
66 |
67 | - **调用拓扑图**:主要突出系统内各个子服务的全局关系、调用依赖关系。作为全局视角图,它帮助工程师理解全局系统、并识别瓶颈。例如,若某服务压力过高,调用拓扑图的拓展区(右侧)会显示该服务详细情况(延迟、load、QPS 等)。
68 | :::center
69 | 
70 | 图 9-15 Pinpoint 的调用拓扑图
71 | :::
72 |
73 |
74 | [^1]: 参见《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》https://research.google/pubs/dapper-a-large-scale-distributed-systems-tracing-infrastructure/
75 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 深入高可用系统原理与设计
2 |
3 |
4 | ## 这是什么?
5 |
6 | 这是一本关于架构设计的开源书籍,已经完稿。如果阅读文章发现问题,欢迎在 github 给我提交 PR 或者 issue。
7 |
8 | 以下为我的公众号,欢迎与我讨论技术。
9 |
https://github.com/isno/theByteBook
27 | ::: 28 | 29 | 30 | 31 | ## 如何阅读 32 | 33 | - **在线阅读**:本文档在线阅读地址为:[https://www.thebyte.com.cn](https://www.thebyte.com.cn) 【为防止缓存,阅读前请先强制刷新】 34 | 35 | - **离线阅读**: 36 | 37 | - 部署离线站点:文档基于 [VuePress 2](https://v2.vuepress.vuejs.org/zh/) 构建,如你希望在本地搭建文档站点,请使用如下命令: 38 | 39 | ```bash 40 | # 克隆获取源码 41 | $ git clone https://github.com/isno/theByteBook.git && cd theByteBook 42 | 43 | # 安装工程依赖 44 | $ npm install 45 | 46 | # 运行网站,地址默认为 http://localhost:8080 47 | $ npm run dev 48 | ``` 49 | 50 | 51 | ## ©️ 转载 52 | 53 |图 2-4 Facebook宕机
10 |图 2-5 Cloudflare 的域名解析服务器 1.1.1.1 在 Facebook 故障时请求瞬间增大 30 倍
33 |图 2-6 amazon.com 与 facebook.com 域名系统对比
63 |