站点可靠性工程SRE最佳实践 -- 黄金监控信号

news2024/11/29 6:37:49

延迟、流量、错误率、饱和度这四大黄金信号是SRE的最佳实践,可用来帮助SRE团队快速评估系统状态,在异常情况下及时介入,保证系统始终工作在健康状态。原文: Four Golden Signals Of Monitoring: Site Reliability Engineering (SRE) Metrics[1]

黄金信号(Golden Signals)最初是谷歌在站点可靠性工程(SRE)实践的背景下引入的,由谷歌软件工程师Dave Rensin和Kevin Smathers在2016年O 'Reilly Velocity Conference上的一次演讲中提出,其背后的想法是提供一组关键性能指标(KPI),用于测量和监控复杂分布式系统的运行状况。

引入黄金信号是为了帮助SRE团队关注系统可靠性和性能方面真正重要的东西。黄金信号不依赖于难以解释的大量指标和告警,而是提供一组简单且易于理解的指标,用于快速评估系统健康状况。

自从这一概念提出以来,黄金信号已在SRE社区中得到广泛采用,并被认为是监控和管理分布式系统运行状况的最佳实践。虽然最初黄金信号专注于延迟、流量、错误和饱和指标,但一些组织已经调整了这个概念,引入了特定于其系统和用例的附加指标。不过,通过一组KPI来度量和监控系统健康的核心思想仍然是黄金信号概念的核心。

什么是黄金信号?

黄金信号是SRE用来衡量其系统健康状况的一组四个关键指标,包括:

  1. 延迟(Latency) —— 延迟用来度量系统响应请求所需的时间,延迟高表明系统可能过载或遇到其他性能问题。
延迟
延迟

Prometheus查询histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket{job="fastapi-app"}[5m])) by (le, method, endpoint))通过直方图指标(histogram metric)度量来检测FastAPI应用程序HTTP请求的P95延迟。

该查询计算过去5分钟内http_request_duration_seconds_bucket度量值(表示落入特定延迟桶的请求数量)的速率总和,并按延迟(le)、HTTP方法和端点分组。然后,histogram_quantile函数使用这些值计算每个HTTP方法和端点组合的P95延迟。

  1. 流量(Traffic) —— 流量衡量流经系统的数据或请求的数量,流量高表明系统可能正在处理大量请求,或者系统容量存在问题。
流量
流量

Prometheus查询rate(http_requests_total{job="fastapi-app"}[$__rate_interval])通过计数器指标(counter metric)度量FastAPI应用程序每秒HTTP请求的速率。

该查询使用rate函数来计算http_requests_total计数器指标的每秒增长率,计算向FastAPI应用程序发出的HTTP请求总数。job="fastapi-app"标签选择器过滤度量数据,使其只包含来自FastAPI的数据。

$__rate_interval变量是模板变量,表示计算速率的持续时间,该变量值由用户在Prometheus查询界面中设置,用于确定计算速率的时间范围。

例如,如果用户将$__rate_interval设置为5m,查询将计算过去5分钟内HTTP请求的每秒速率。此查询可用于监控FastAPI应用程序的流量,并识别请求量随时间变化的模式或异常情况。

  1. 错误(Errors) —— 错误度量系统中发生的错误数量,错误率高表明系统中可能存在bug或其他问题。
错误数
错误数

Prometheus查询http_requests_total {endpoint="/generate_error", http_status="500"}检索web应用程序的"/generate_error"端点的HTTP请求并且HTTP状态码为500(内部服务器错误)的数量。

该查询使用http_requests_total计数器指标,计算向web应用程序发出的HTTP请求总数。查询通过指定endpoint="/generate_error"标签选择器过滤度量数据,使其只包括对"/generate_error"端点的请求。此外,查询通过指定http_status="500"标签选择器过滤数据,只包括HTTP状态码为500的请求。

通过运行这个查询,可以深入了解web应用中错误发生率,以及哪些端点容易出错。这些信息可以帮助识别和修复应用中的问题,提高可靠性,并确保为用户提供更好的体验。

  1. 饱和度(Saturation) —— 饱和度衡量系统的资源利用率,饱和度高表明系统资源(例如CPU或内存)可能正在被耗尽。
饱和度
饱和度

Prometheus查询clamp_max(active_requests{job="fastapi-app"} / 10, 1)用于计算活动请求与最大并发请求数的比率,并将该比率的值限制为不超过1。

该查询使用active_requests度量(gauge)指标检索FastAPI应用程序中的当前活动请求数。job="fastapi-app"标签选择器过滤度量数据,使其只包含来自FastAPI的数据。

然后,查询将活动请求数除以10,表示系统可以处理的最大并发请求数。然后使用clamp_max函数将该比率的值限制为不超过1。这意味着,如果活动请求与最大并发请求数之比大于1,则查询将返回值1。

通过这个查询,可以监控系统饱和情况,并确定系统何时因请求而过载。如果活动请求与最大并发请求数之比接近1,可能需要扩容系统以处理增加的请求。此查询可以帮助我们确保系统在高负载下仍可保持可靠和高性能。

为什么黄金信号很重要?

因为黄金信号使SRE们可以清楚了解系统的运行情况,因此非常重要。通过测量和监控这些关键指标,SRE可以快速识别问题,并在问题变得严重之前采取纠正措施,即使这么做增加了系统复杂性,也可以有助于确保系统的可靠性、可伸缩性和高性能。

如何使用黄金信号来提高系统可靠性?

黄金信号可以通过几种方式来提高系统可靠性:

  1. 主动监控(Proactive Monitoring) —— 通过持续监控黄金信号,SRE可以在问题变得严重之前识别问题,从而能够采取主动措施来防止停机或其他性能问题。
  2. 容量规划(Capacity Planning) —— 黄金信号可用于识别系统何时达到其容量限制。通过监控流量和饱和度指标,SRE可以做出明智决定,决定何时升级或扩容系统以满足需求。
  3. 根因分析(Root Cause Analysis) —— 当系统出现问题时,SRE可以使用黄金信号来帮助确定问题的根本原因。通过查看延迟、流量、错误和饱和度指标,SRE可以深入了解出了什么问题,并采取措施防止将来发生类似问题。

了解如何在实践中实现这些指标也很重要。实现黄金信号的一种方法是使用内置对其支持的监控工具和库,比如Prometheus。在下面代码示例中,Python FastAPI应用程序通过Prometheus来实现黄金信号。

from fastapi import FastAPI, Request, HTTPException, Response
from prometheus_client import Counter, Gauge, Histogram, generate_latest, CONTENT_TYPE_LATEST
from starlette.responses import StreamingResponse
import time

app = FastAPI()

# Define Prometheus metrics
http_requests_total = Counter(
    "http_requests_total",
    "Total number of HTTP requests",
    ["method""endpoint""http_status"]
)
http_request_duration_seconds = Histogram(
    "http_request_duration_seconds",
    "HTTP request duration in seconds",
    ["method""endpoint"]
)
http_request_size_bytes = Histogram(
    "http_request_size_bytes",
    "HTTP request size in bytes",
    ["method""endpoint"]
)
http_response_size_bytes = Histogram(
    "http_response_size_bytes",
    "HTTP response size in bytes",
    ["method""endpoint"]
)
active_requests = Gauge(
    "active_requests",
    "Number of active requests"
)
error_counter = Counter(
    "error_counter",
    "Total number of HTTP errors",
    ["method""endpoint""http_status"]
)

@app.middleware("http")
async def record_request_start_time(request: Request, call_next):
    request.state.start_time = time.time()
    response = await call_next(request)
    return response

@app.middleware("http")
async def record_request_end_time(request: Request, call_next):
    response = await call_next(request)
    latency = time.time() - request.state.start_time
    http_request_duration_seconds.labels(
        request.method, request.url.path
    ).observe(latency)
    http_request_size_bytes.labels(
        request.method, request.url.path
    ).observe(request.headers.get("Content-Length"0))
    if isinstance(response, StreamingResponse):
        response_size = 0
    else:
        response_size = len(response.content)
    http_response_size_bytes.labels(
        request.method, request.url.path
    ).observe(response_size)
    http_requests_total.labels(
        request.method, request.url.path, response.status_code
    ).inc()
    return response

@app.middleware("http")
async def increment_counter(request: Request, call_next):
    active_requests.inc()
    response = await call_next(request)
    active_requests.dec()
    return response

@app.middleware("http")
async def log_saturation(request: Request, call_next):
    max_concurrent_requests = 10  # set the maximum number of concurrent requests
    saturation_ratio = active_requests._value._value / max_concurrent_requests
    print(f"Saturation: {saturation_ratio}")
    return await call_next(request)

@app.middleware("http")
async def increment_error_counter(request: Request, call_next):
    try:
        response = await call_next(request)
        return response
    except HTTPException as e:
        error_counter.labels(
            request.method, request.url.path, e.status_code
        ).inc()
        print(f"Incremented error counter for {request.method} {request.url.path} {e.status_code}")
        raise e


@app.get("/")
async def root():
    return {"message""Hello, World!"}


@app.get("/generate_traffic")
async def generate_traffic():
    for i in range(100):
        response = await root()
        print(response)
    return {"message""Generated traffic successfully."}


@app.get("/generate_error")
async def generate_error():
    raise HTTPException(status_code=500, detail="Generated an error.")


@app.get("/metrics")
async def metrics():
    return Response(content=generate_latest(), media_type=CONTENT_TYPE_LATEST)

requirements.txt:

anyio==3.6.2
click==8.1.3
fastapi==0.92.0
h11==0.14.0
idna==3.4
prometheus-client==0.16.0
pydantic==1.10.5
sniffio==1.3.0
starlette==0.25.0
typing_extensions==4.5.0
uvicorn==0.20.0
在K8S上部署

使用Prometheus在FastAPI应用程序中实现了黄金信号后,可能希望将其部署到Kubernetes集群中,以确保可伸缩性和高可用性。下面的Kubernetes清单文件可以用来部署FastAPI应用程序和Grafana仪表板:

fastapi-app.yaml

# @format

apiVersion: apps/v1
kind: Deployment
metadata:
  name: fastapi-app
spec:
  selector:
    matchLabels:
      app: fastapi-app
  replicas: 2
  template:
    metadata:
      labels:
        app: fastapi-app
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/path: "/"
        prometheus.io/port: "80"
    spec:
      containers:
        - name: fastapi-app
          image: rtiwariops/fastapi-app:v1
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: fastapi-app
spec:
  selector:
    app: fastapi-app
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80

grafana.yaml

# @format

apiVersion: apps/v1
kind: Deployment
metadata:
  name: grafana
spec:
  selector:
    matchLabels:
      app: grafana
  replicas: 1
  template:
    metadata:
      labels:
        app: grafana
    spec:
      containers:
        - name: grafana
          image: grafana/grafana:latest
          ports:
            - containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
  name: grafana
spec:
  selector:
    app: grafana
  ports:
    - name: http
      protocol: TCP
      port: 3000
      targetPort: 3000

prometheus.yaml

apiVersion: v1
kind: Service
metadata:
  name: prometheus
spec:
  selector:
    app: prometheus
  ports:
    - name: web
      port: 9090
      targetPort: 9090
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus
spec:
  selector:
    matchLabels:
      app: prometheus
  replicas: 1
  template:
    metadata:
      labels:
        app: prometheus
    spec:
      containers:
      - name: prometheus
        image: prom/prometheus:v2.28.1
        ports:
        - name: web
          containerPort: 9090
        command:
        - "/bin/prometheus"
        args:
        - "--config.file=/etc/prometheus/prometheus.yml"
        volumeMounts:
        - name: config-volume
          mountPath: /etc/prometheus
      volumes:
      - name: config-volume
        configMap:
          name: prometheus-config

总之,黄金信号是SRE工具箱中的关键工具。通过测量和监控延迟、流量、错误和饱和度指标,即使面对日益增加的复杂性和需求,SRE也可以确保其系统保持可靠、可扩展和高性能。

完整代码示例: https://github.com/PolyCloudNative/Golden-Rule-Demo


你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。
微信公众号:DeepNoMind

参考资料

[1]

Four Golden Signals Of Monitoring: Site Reliability Engineering (SRE) Metrics: https://umeey.medium.com/four-golden-signals-of-monitoring-site-reliability-engineering-sre-metrics-64031dbe268

- END -

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1286280.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

创建 Python Docker 镜像的完整指南

更多资料获取 📚 个人网站:ipengtao.com Python和Docker是两个极其流行的技术,结合它们可以创建强大的应用程序。Docker允许将应用程序及其依赖项打包到一个独立的容器中,而Python则提供了丰富的库和工具来开发应用程序。本文将提…

群晖NAS配置之自有服务器ngrok实现内网穿透

群晖NAS配置之自有服务器ngrok实现内网穿透 前言-内网穿透 内网穿透是指通过一种技术让外部网络可以访问到内网的NAS设备,这样即使在不同网络环境下,也能够远程访问和管理NAS设备。以下是一些常见的内网穿透方案: Synology官方提供的Quick…

华盛顿特区警方推荐购买 AirTag防止高端夹克被窃

根据美国媒体 Fox5 报道,近期由于天气变冷,华盛顿特区已发声多起高端 Canada Goose 夹克被窃事件。这些被偷走的加拿大鹅夹克价格从几百到几千美元不等,“Canada Goose”LOGO较为明显,很容易被小偷发现。 对此,警方建…

nodejs+vue+elementui校园演出赞助艺术资源管理系统

系统主要分为系统管理员和学生、校外人员三个部分,系统管理员主要功能包括:首页、个人中心、学生管理、校外人员管理、社团信息管理、校内演出管理、校外商演管理、系统管理;基本上实现了整个基于vue的校园艺术资源管理系统的设计与实现信息管…

SpringBoot3-快速体验

1、pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.…

Linux性能系统学习之监控工具

目录 前言linux性能度量标准监控工具topuptimeps/pstreefreempstatvmstat 前言 在实际产品开发过程中遇到一些莫名其妙的问题&#xff0c;比如swap交换分区随着时间增多影响到系统调用&#xff0c;或CPU占用以及内存的监测等&#xff0c;所以有必要系统了解Linux的性能问题。 …

CUDA简介——For循环并行化

1. 引言 前序博客&#xff1a; CUDA简介——基本概念CUDA简介——编程模式 kernel相关语法定义为&#xff1a; kernel函数定义&#xff0c;与常规C函数定义类似。不同之处在于&#xff0c;有__global__关键字。 为说明符&#xff0c;告诉编译器该函数应编译运行在device上&a…

极客大挑战2023 Reverse wp

文章目录 [toc] shiftjmp点击就送的逆向题幸运数字flower-or-tea小黄鸭mySelfeasymath听说cpp很难&#xff1f;砍树浪漫至死不渝是男人就来扎针ezandroid shiftjmp 64bit的ELF文件&#xff0c;IDA打开 考察花指令去除、将E9 nop掉 EXP&#xff1a; enc [ 0x53, 0x58, 0x41, 0…

面向注解编程—Spring 注解看这一篇就够了(2)

面向注解编程—Spring注解大全&#xff08;AOP篇&#xff09; AOP英文全称&#xff1a;Aspect Oriented Programming&#xff08;面向切面编程、面向方面编程&#xff09;&#xff0c;其实说白 了&#xff0c;面向切面编程就是面向特定方法编程。 AOP的作用&#xff1a;在程序…

【好书推荐】Flutter入门经典

目录 作者简介内容简介文章详解介绍《Flutter入门经典》读者对象《Flutter入门经典》内容要点《Flutter入门经典》内容结构第I部分&#xff1a;Flutter编程基础第II部分&#xff1a;充当媒介的Flutter&#xff1a;具象化一个应用第III部分&#xff1a;创建可用于生产环境的应用…

广州数字孪生赋能工业制造,加速推进制造业数字化转型

广州数字孪生赋能工业制造&#xff0c;加速推进制造业数字化转型。数字孪生系统基于历史数据、实时数据&#xff0c;采用人工智能、大数据分析等新一代信息技术对物理实体的组成、特征、功能和性能进行数字化定义和建模。通过构建在信息世界对物理实体的等价映射&#xff0c;对…

Geodesic in Heat: 一种测地线计算方法

在之前的博客中&#xff0c;我已经介绍过了使用Fast Marching算法计算测地线。Fast Marching的好处是实现简单&#xff0c;方便扩展在点云上。但是缺点是精度不够&#xff0c;求解不平滑。早在2013年&#xff0c;Crane et al. [1]就已经提出利用热流来估算测地距离。我很早就知…

深入理解Java核心技术:Java工程师的实用干货笔记

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 在Java工程师的职业生涯中&#xff0c;深入理解…

使用C语言创建高性能网络爬虫IP池

目录 一、引言 二、IP池的设计 1、需求分析 2、架构设计 3、关键技术 三、IP池的实现 1、存储实现 2、调度实现 3、通信实现 4、异常处理实现 四、代码示例 五、性能优化 六、测试与分析 七、结论 一、引言 随着互联网的快速发展&#xff0c;网络爬虫成为了获取…

日志JavaAgent-NoClassDefFoundError

一、引言 组内最近做了一个日志公共组件&#xff0c;用的是javaagent的方式&#xff0c;之前搞的maven jar包每次都要把所有系统都发一遍&#xff0c;太麻烦。 javaagent通过Java虚拟机&#xff08;JVM&#xff09;的Instrumentation API来实现代码的侵入。通过Instrumentation…

matlab diff和gradient

gradient 求解梯度。 示例 FX gradient(F) 返回向量 F 的一维数值梯度。输出 FX 对应于 ∂F/∂x&#xff0c;即 x&#xff08;水平&#xff09;方向上的差分。点之间的间距假定为 1。 使用方法&#xff1a; x -2:0.2:2; y x’; z x .* exp(-x.^2 - y.^2); [px,py] gradien…

K8S部署nginx并且使用NFS存储数据

安装NFS 在master安装NFS systemctl start nfs-server修改配置 /etc/exports /data *(rw,no_root_squash,no_all_squash,sync)目录为 /data 允许所有地址访问 验证下 [rootmaster nginx]# showmount -e 192.168.57.61 Export list for 192.168.57.61: /data *共享可以正常…

1.uniapp基础

1.uniapp基础 官方文档&#xff1a;uni-app官网 1.1开发工具 &#xff08;1&#xff09;工具&#xff1a; HBuilderX HBuilderX-高效极客技巧 1.2 新建项目 &#xff08;1&#xff09; 文件》新建项目 ​ &#xff08;2&#xff09;选择相应的配置信息&#xff0c;填写项目根路…

python超详细基础文件操作【建议收藏】

文章目录 前言1 文件操作1.1 文件打开与关闭1.1.1 打开文件1.1.2 关闭文件 1.2 访问模式及说明 2 文件读写2.1 写数据&#xff08;write&#xff09;2.2 读数据&#xff08;read&#xff09;2.3 读数据&#xff08;readlines&#xff09;2.3 读数据&#xff08;readline&#x…

数据结构 / 队列 / 循环队列 / 概念

1. 定义 为充分利用向量空间&#xff0c;克服假溢出现象的方法是&#xff1a;将向量空间想象为一个首尾相接的圆环&#xff0c;并称这种向量为循环向量。存储在其中的队列称为循环队列&#xff08;Circular Queue&#xff09;。循环队列是把顺序队列首尾相连&#xff0c;把存储…