第05期:Prometheus 数据查询(一)

本期作者:沈亚军
爱可生上海研发中心成员,研发工程师。


Prometheus 数据基本查询

上篇文章【第04期:Prometheus 数据采集(三)】介绍了 Prometheus 数据采集流程,本文开始将介绍 Prometheus 数据查询。本文会介绍数据查询的基本使用。

PromQL 简介

Prometheus 通过指标名称(metrics name)以及对应的一组标签(labelset)唯一定义一条时间序列。指标名称反映了监控样本的基本标识,而 label 则在这个基本特征上为采集到的数据提供了多种特征维度。用户可以基于这些特征维度过滤,聚合,统计从而产生新的计算后的一条时间序列。Prometheus 提供了一种称为 PromQL 的功能查询语言,使用户可以实时选择和汇总时间序列数据。表达式的结果可以显示为图形,可以在 Prometheus 的表达式浏览器中显示为表格数据,也可以由外部系统通过 HTTP API 使用。在 Prometheus 的表达语言中,一个表达式或子表达式可以计算为以下四种类型之一:

  • 瞬时向量(Instant vector):一组时间序列,每个时间序列包含一个样本,所有样本共享相同的时间戳。
  • 范围向量(Range vector):一组时间序列,其中包含每个时间序列随时间变化的一系列数据点。
  • 标量(Scalar):一个简单的数字浮点值。
  • 字符串(String):一个简单的字符串值,目前未使用。

PromQL 基本使用

时间序列选择器

瞬时向量选择器

瞬时向量选择器允许在给定的时间戳上选择一组时间序列和每个样本的单个采样值,返回值中只会包含该时间序列中的最新的一个样本值。

当我们直接使用监控指标名称查询时,可以查询包含该 metric 名称的所有时间序列。以下两种表达方式是等同的:

http_requests_total

该表达式会返回指标名称为 http_requests_total 的所有时间序列。

http_requests_total{code="200",handler="alerts",instance="localhost:9090",job="prometheus",method="get"}=(20889@1518096812.326)

通过在花括号 {} 中添加逗号分隔的标签匹配器列表,可以进一步过滤这些时间序列。

如果我们只需要查询所有 http_requests_total 时间序列中满足标签 job 为 prometheus 且 group 为 canary 的时间序列,可以使用如下表达式。

http_requests_total{job="prometheus",group="canary"}

PromQL 还支持用户根据时间序列的标签匹配模式来对时间序列进行过滤,目前主要支持两种匹配模式:完全匹配和正则匹配。

  • 通过使用 label=value 可以选择那些标签满足表达式定义的时间序列

  • 反之使用 label!=value 则可以根据标签匹配排除时间序列

  • 使用 label=~regx 表示选择那些标签符合正则表达式定义的时间序列

  • 反之使用 label!~regx 进行排除

例如,如果想查询多个环节下的时间序列序列可以使用如下表达式:

http_requests_total{environment=~"staging|testing|development",method!="GET"}

在标签匹配中如果指定标签值为空,会匹配所有不包含该标签的时间序列,同一标签名称可有多个匹配器。

向量选择器必须指定一个名称或至少一个与空字符串不匹配的标签匹配器。

以下表达式是非法的,

{job=~".*"}

相反,这些表达式是有效的,因为它们都有一个与空标签值不匹配的选择器。

{job=~".+"}

标签匹配还以使用内部的 ** name** 标签应用到 metric 名称,如 http_requests_total 等同于**{name=“http_requests_total”}**,
下面的表达式会筛选出所有以 **job:**开头的 metric,

{__name__=~"job:.*"}

另外 metric 名称不能包含以下关键字:boolonignoringgroup_leftgroup_right 可使用如下方式代替,

{__name__="on"}

Prometheus 中的所有正则表达式都使用 RE2 syntax.

RE2 syntax:
https://github.com/google/re2/wiki/Syntax

区间向量选择器

范围向量文字的工作方式与即时向量文字相同,不同之处在于,它们从当前瞬间选择了一定范围的样本。语法上,将范围持续时间附加在向量选择器末尾的方括号([])中,以指定应为每个结果范围向量元素提取多远的时间值。

区间向量表达式和瞬时向量表达式之间的差异在于在区间向量表达式中我们需要定义时间选择的范围,时间范围通过时间范围选择器 [] 进行定义。

时间范围选择器内容指定为数字,紧随其后的是以下单位之一:

  • s - seconds
  • m - minutes
  • h - hours
  • d - days
  • w - weeks
  • y - years

例如,如通过以下表达式可以选择最近 5 分钟内的所有样本数据:

http_requests_total{job="prometheus"}[5m]
时间偏移

在瞬时向量表达式或者区间向量表达式中,都是以当前时间为基准。

http_request_total{} # 瞬时向量表达式,选择当前最新的数据

而如果我们想查询,5 分钟前的瞬时样本数据,或昨天一天的区间内的样本数据呢?这个时候我们就可以使用位移操作,可以使用 offset 时间位移操作:

http_request_total{} offset 5m

需要注意的是 offset 关键词需要紧跟在选择器之后。

sum(http_requests_total{method="GET"} offset 5m) // 正确

存储设计原理简介

时序数据的存储分俩个维度,如下图所示,纵轴表示所有存储的序列数据,横轴表示数据的时间分布:

promutheus 会定期拉取数据,从横轴的右侧垂直写入数据, 而我们在执行查询的时候,往往是查询图中任意矩形区域的数据,时序数据的存储和读取模式有着很大的差异,为了同时满足写入和查询两种不同需求,对存储层的时间有比较高的要求,如果在 k8s 环境,由于 pod 不断的新建和重启,时序数据会变成如下图的线性分布,更是提高了存储和查询难度。

样本数据压缩

Prometheus 每秒会采集大量的数据,数据压缩势在必行,Prometheus 基于同一个序列的数据相似度比较高,在内存可以把每个数据点压缩到平均 1.37 byte 大小。

时间分片

Prometheus 的存储层把数据划分成了不同的块,如下图所示:

每个块保存了在该时间段内的序列数据,每个数据块可以单独行使数据库行为,优点如下:

  • 在指定一个时间范围时只需要查询其中一些子块,能有效的减少查询时间。

  • 解决了由于服务不断的新建和重启,时间序列数据呈线性分布的问题。

  • 更方便的根据时间删除过期数据。

倒排索引

通常情况下用户会根据标签检索数据,但是由于标签是用户自定义不同的应用会有不同的标签,因此不能像传统数据库一样在标签上建立索引,为了提高查询效率,因此 Prometheus 把每个时序的描述当作一个小文档,建立了倒排索引,如:requests_total{path="/status",method=“GET”, instance=“10.0.0.1:80”} 的文档包含如下关键词:name=“requests_total”path="/status"method=“GET”instance="10.0.0.1:80,对于每个时序数据唯一的 label 会为其建立额外的索引行,每个索引行对应一个有序的 ID 列表,每个 ID 对应一条时序数据,这些列表可高效的合并或相交,以满足复杂的查询场景。

常用函数和操作符介绍

rate

rate 是专门搭配 counter 类型数据使用的函数,计算范围向量中时间序列的每秒平均增长率,当counter 出现单调性中断会自动进行调整,计算时会根据有效值在时间范围内的比例扩大时间区间范围,从而允许数据丢失或时间范围与数据拉取的时间段不完全对齐。

如:计算 job 为 api-server 的请求在 5m 内增长率。

rate(http_requests_total{job="api-server"}[5m])

irate

irate 适用于变化频率高的 counter 类型数据,计算范围向量中时间序列的每秒平均增长率。基于最后两个数据点。当 counter 出现单调性中断会自动进行调整,与 rate 不同的是,irate 只会选取时间范围内最近的两个点计算,当选定的时间范围内仅包含两个数据点时,不考虑外推情况,rateirate 并无明显区别。

如:计算 job 为 api-server 的请求在 5m 内增长率。

irate(http_requests_total{job="api-server"}[5m])

predict_linear

predict_linear 可用于 gauges 类型数据,predict_linear 函数可以预测时间序列 v 在 t 秒后的值,它基于简单线性回归的方式,对时间窗口内的样本数据进行统计,从而可以对时间序列的变化趋势做出预测。例如,基于 2 小时的样本数据,来预测主机可用磁盘空间的是否在 4 个小时候被占满,可以使用如下表达式:

predict_linear(node_filesystem_free{job="node"}[2h], 4 * 3600) < 0

当资源占用不是平滑变化的使用 predict_linear 可以做到提前预警,可以有效避免基于资源用量是平滑增长的的阈值告警模式出现的告警还未来的及处理系统就不可用的情况。

聚合操作符

PrmoQL 提供了内置的聚合操作符,包括 summinmaxavggroupcoun****t etc,表达方** [without|by (

sum without (instance) (http_requests_total) // HTTP requests per application and group

使用建议

聚合操作符的使用顺序

  • 先使用 sum 再使用 rate,原因是在服务器重启的情况下 counter 会被置 0,如果先使用 sum 再使用 rate,重启现象会被掩盖,从而会出现假峰值,其它类似的操作符和函数还有 minmaxavgceilhistogram_quantilepredict_linear etc。

  • 可直接安全的作用与 counter 的操作符有 rateirateincreaseresets 其它都需要慎重考虑引起的其它问题。

避免慢查询和数据过载

  • 当数据量很大时,对其直接进行查询或绘图时很有可能导致服务器或浏览器过载或超时,合理的做法是指定合理的时间范围和查询步长,可以在 Prometheus 自带的查询界面构建查询表达式增加标签进行筛选或聚合,直到获得一个合理的查询结果集。

  • 当使用以上方式仍不能完全缓解查询压力,可以通过 Recording Rules 保存常用的查询数据以提高查询效率。

**Recording Rules:**https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/#recording-rules

时间范围和数据拉取间隔

时间范围通常大于等于 4 倍数据拉取时间间隔,举例:当数据拉取间隔为 10s, rateirate 至少需要两个样本点,所以需要 30s 来保证至少覆盖两个时间点,考虑到某个时间点拉取出错,所以 40s 是一个较为合理的时间范围,实际使用通常取整到 1m 举例:irate(http_requests_total{job=“api-server”}[1m])

  • 对于 irate 指定一个大的时间范围没有意义的,通常指定为四倍数据拉取时间间隔

  • 对于 rate 没有明确的建议,需要考虑的是时间范围越大,会拉平出现的数据峰值,获得更为平缓的速率

irate 和 rate 和查询步长

  • 当调用 /api/v1/query_range 获取绘图数据时,需要指定参数 query 查询范围,指定获取时间序列样本量的大小,step 查询步长,查询步长决定了绘图点的个数,步长越小绘图点越多,考虑到图的直观及可读性需要选择合适的步长。

  • irate 适合快速变化的计数器, 当查询步长大于 irate 时间范围时,由于其只取最后两个数据点,可能会导致在时间范围外的数据峰值点未能被捕获,查询步长与其时间范围越接近, 会捕获更多的数据峰值,曲线变化也更灵敏精确,推荐在重要且需要监测其细节变化的 metric 中使用。

  • 大多数情况下我们可以使用 rate,但需要注意的是时间范围不应当小于步长,否则可能会漏掉数据。


相关内容方面的知识,大家还有什么疑问或者想知道的吗?赶紧留言告诉小编吧!

<think>好的,我现在需要帮用户详细讲解如何实施他们搭建自动应答系统的第阶段。用户之前已经询问过整体方案,现在他们特别关注第阶段的具体步骤。作为技术转型的电商从业者,用户可能需要既明确技术实现,又能结合业务需求。 首先,回顾之前的对话,用户得到了个分阶段的建议,现在需要展开第阶段。用户可能希望了解从零开始搭建最小可行系统(MVP)的具体步骤,包括技术选型、开发流程、集成大模型等。他们可能对技术细节不太熟悉,所以需要用易懂的语言解释,同时提供可操作的指导。 接下来,我需要考虑用户可能的实际需求。他们提到的是拼多多客服系统,所以需要符合电商平台的特点,比如处理常见问题、订单查询,以及合规性要求。第阶段的目标是处理简单咨询,因此重点可能在快速上线核心功能,验证可行性,同时为后续阶段打下基础。 用户可能有隐藏的需求,比如成本控制、系统稳定性、以及未来的扩展性。在回答中需要涵盖这些方面,例如使用成本效益高的技术栈,设计可扩展的架构,以及监控和测试机制确保系统稳定。 需要分步骤讲解,从需求分析开始,明确核心功能和非核心功能,然后进行技术选型,比如使用FastAPI和DeepSeek,接着是开发流程,包括API搭建、大模型集成、对话管理等。还要考虑数据准备、测试部署、成本控制以及下步计划。 确保每个步骤都有具体的代码示例或配置,帮助用户实际操作。同时,强调注意事项,如合规性、性能优化和扩展性,避免用户在实际操作中遇到问题。 最后,总结第阶段的关键点,确保用户理解这是个迭代过程,MVP的目标是快速验证和收集反馈,为后续开发奠定基础。可能还需要提醒用户关注拼多多的平台规范,确保系统符合要求,避免上线后出现问题。</think>以下是搭建基于大模型的7*24小时自动应答系统**第阶段**的详细实施指南(聚焦快速搭建最小可行系统): --- ### **、需求聚焦(MVP核心)** **核心目标**:用最快速度上线能处理60%高频简单问题的系统 **业务范围**: 1. 商品咨询(规格/价格/发货地) 2. 订单状态基础查询 3. 退换货政策问答 4. 平台规则解释(如拼团时效) **技术指标**: - 响应时间 ≤1.5秒 - 日均承载5000次请求 - 异常率<1% --- ### **二、技术选型清单** | 组件 | 推荐方案 | 选择理由 | |--------------|--------------------------|-----------------------------------| | Web框架 | FastAPI | 异步高性能,自带API文档 | | 大模型 | DeepSeek-Chat | 中文场景优化,API成本可控 | | 数据库 | Redis | 高频对话状态存储 | | 部署 | Docker + Nginx | 快速容器化部署 | | 监控 | Prometheus + Grafana | 开源方案易集成 | --- ### **三、开发步骤详解** #### **1. 基础API搭建(2天)** ```python # main.py 核心代码框架 from fastapi import FastAPI from pydantic import BaseModel app = FastAPI(title="PDD客服机器人V1") class UserRequest(BaseModel): user_id: str query: str session_id: str = None @app.post("/chat") async def chat_endpoint(request: UserRequest): # 此处接入后续处理逻辑 return {"response": "默认响应"} ``` #### **2. 大模型接口集成(1天)** ```python # deepseek_integration.py import os from deepseek_api import DeepSeek DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_KEY") def generate_response(query: str): system_prompt = """你是有拼多多平台知识的智能客服,请用口语化中文回答: 1. 不超过50字 2. 避免专业术语 3. 遇到不确定问题时引导用户转人工""" return DeepSeek(api_key=DEEPSEEK_API_KEY).chat( messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": query} ], temperature=0.3 ) ``` #### **3. 基础对话管理(1天)** ```python # session_manager.py from redis import Redis redis_conn = Redis(host='localhost', port=6379, db=0) def handle_session(user_id: str, query: str): session_key = f"session:{user_id}" # 获取最近3轮对话历史 history = redis_conn.lrange(session_key, 0, 2) # 更新对话记录(保留最新5轮) redis_conn.lpush(session_key, query) redis_conn.ltrim(session_key, 0, 4) return history ``` --- ### **四、电商知识库准备** **数据来源优先级**: 1. **官方文档**:拼多多商家后台的《客服应答规范》《售后政策文档》 2. **历史工单**:导出近3个月人工客服对话记录(脱敏后) 3. **商品数据库**:CSV格式导出SKU基础信息表 **知识库格式示例**: ```csv question,answer "什么时候发货","普通商品将在下单后48小时内发货,预售商品按页面显示时间发货" "怎么修改地址","订单未发货时可联系客服修改,已发货需联系快递公司" ``` --- ### **五、测试与部署方案** #### **压力测试脚本** ```python # test_load.py import httpx import asyncio async def stress_test(): async with httpx.AsyncClient() as client: tasks = [] for _ in range(100): # 模拟100并发 task = client.post( "http://localhost:8000/chat", json={"user_id": "test", "query": "什么时候发货"} ) tasks.append(task) responses = await asyncio.gather(*tasks) success = sum(1 for r in responses if r.status_code == 200) print(f"成功率: {success/len(responses)*100}%") ``` #### **Docker部署配置** ```dockerfile FROM python:3.9-slim RUN pip install fastapi uvicorn redis deepseek-api COPY . /app WORKDIR /app CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] ``` --- ### **六、成本控制(首预算)** | 项目 | 预估费用 | 说明 | |----------------|-----------|--------------------------| | 服务器 | ¥500/月 | 2核4G云服务器(阿里云) | | DeepSeek API | ¥0.3/千次| 按实际调用量计费 | | Redis | ¥0 | 使用云服务器自建 | | 带宽 | ¥200/月 | 5Mbps固定带宽 | --- ### **七、第阶段验收标准** 1. **功能验证**: - 能准确回答《高频问题清单》中的50个标准问题 - 错误回答时能引导转人工(预设关键词:转人工/找客服) 2. **性能验证**: - 50并发请求下响应时间≤2秒 - 持续运行24小时无内存泄漏 3. **业务验证**: - 接入1个测试店铺真实咨询流 - 人工接管率<40% --- ### **八、下步衔接准备** 在完成第阶段后立即启动: 1. 开发订单查询API对接模块 2. 构建FAQ知识库向量搜索引擎 3. 实现敏感词动态过滤系统 --- **关键提醒**:建议使用你的编程能力开发个`对话模拟测试工具`,批量输入测试用例并自动检查是否符合《拼多多客服应答规范》。可参考以下伪代码逻辑: ```python def test_response(query, expected_keywords): response = generate_response(query) assert any(kw in response for kw in expected_keywords), f"应答不符合规范: {query}" ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值