Trace、Metrics、Logging 选型

news2024/11/19 19:41:35

背景

分布式追踪的起源

自从微服务的兴起开始,整个系统架构开始变得极为庞大和复杂,但是服务之间的调用关系,调用消耗时间等等信息却依然是半黑盒的状态。为了能够将调用的链路进行串联,将系统的各种指标数据展示出来以使得系统的链路更加透明便于排查故障,分布式追踪便应运而生。

百花齐放的分布式追踪

Zipkin

Zipkin最初是由Twitter开发并与2012年开源的一款开源追踪系统。Zipkin的使用非常广泛,影响了很多的后来人。他的传输头为X-B3

Skywalking

Skywalking是由国人开发,并且在后续捐赠给了Apache基金会的一个开源项目。现在是Apache基金会的顶级项目。

Pinpoint

Pinpoint由Naver在2012年开发,并于2015年开源。Pinpoint适用于java,php和python。

Jaeger

Jaeger最早是由Uber开发并于2017年开源,后续捐赠给了CNCF基金会。

OpenTracing

OpenTracing 的优势在于制定了一套无关厂商、无关平台的协议标准,使开发人员只需要修改 Tracer 就可以更迅捷的添加或更换底层监控的实现,被追踪的服务只需要调用相关 API 接口,就可被任何实现这套接口的追踪后台支持。也是基于这一点,2016 年云原生计算基金会 CNCF 正式接纳 OpenTracing,顺利成为 CNCF 第三个项目。而前两个项目都已成为云原生及开源领域的事实标准–Kubernetes 和 Prometheus,OpenTracing由CNCF托管,具备较为完善的instrumentation库。

遵循 OpenTracing 协议的产品有 Jaeger、Zipkin、 LightStep 和 AppDash 等追踪组件,并可以轻松集成到 gRPC、Flask、Django 和 Go-kit 等开源框架中。

MICROSERVICE PROCESS

APPLICATION CODE

EXISTING INSTRUNENTATION CODE(L

ZIPKIN

LIGHTSTEP

CONTROL FLOW FPAWEWORKS

MAIN()

OPENTRACING

APPDAAK

(MICRO-)SERVICE FRANEWORKS

TRACER

RPC FRANEWORKS

VENDORS

ETC.

OPEN TRACING STANDARDIZES THE DESCRIPTION

OF APPLICATION AND OSS PACKAGE

BEHAVIOR BOTH WITHIN AND BETWEEN

TRACING INFRASTRUCTURE

PROCESSES,ALL WHILE REMAINING

VENDOR-NEUTRAL.

CSON@阿里巴巴云原生

TIME

UNIQUEIDCONTEXT]

EDGE SERVICE

{CONTEXT]

{CONTEXT]

SPANS

TRACE

C

E

D

{CONTEXT]

{CONTEXT)

D

CSDN@阿里巴巴云原生

OpenCensus

OpenCensus由Google发起,最初是Google内部追踪平台,后开源。OpenCensus 提供了统一的测量工具:跨服务捕获跟踪跨度 Span、应用级别指标 Metrics。

• 相较于 OpenTracing 只支持 Traces,OpenCensus 支持 Traces 和 Metrics。

• 相较于 OpenTracing 制定规范,OpenCensus 不仅制定规范,还包含了 Agent 和 Collector。

• 家属团阵容相较 OpenTracing 更加庞大,获得 Google、微软支持。

收集库和应用记录的可观测结果,汇总、导出统计数据,并包括 Recording(记录)、Views(聚合度量查询)两部分。

核心术语介绍

除了沿用 OpenTracing 的相关术语之外,OpenCensus 也定义了一些新术语。

• Tags

OpenCensus 允许在记录时将指标与维度相关联。从而能够从不同角度分析测量结果。

• Stats

收集库和应用记录的可观测结果,汇总、导出统计数据,并包括 Recording(记录)、Views(聚合度量查询)两部分。

• Trace

除了 Opentracing 所提供的 Span 属性之外,OpenCensus 还支持 Parent SpanId、Remote Parent、Attributes、Annotations、Message Events、Links 等属性。

• Agent

OpenCensus Agent 是一个守护进程,允许 OpenCensus 的多语言部署使用Exporter。与传统上为每个语言库和每个应用程序删除和配置 OpenCensus Exporter不同,使用 OpenCensus Agent,只需为其目标语言单独启用 OpenCensus Agent Exporter。对于运维团队而言,实现单个 exporte 管理并从多语言应用程序中获取数据,将数据发送到所选择的后端。与此同时,尽可能的减少反复启动或部署对于应用的影响。最后,Agent 还附带了“Receivers”。“Receivers”使 Agent 直通后端,去接收可观测数据并将其路由到所选择的 Exporter。比如 Zipkin、Jaeger 或 Prometheus。

OPENCENSUS

OC

SERVICE A

COLLECTOR

LIB

JAEGER

OC

SERVICE B

LIB

OPENCENSUS

ZIPKIN

AGENT

SERVICE C

PROMETHEUS

STACKDRIVER

ZIPKIN

SERVICE D

OTHER MONITORING

SERVICE E

OTHER

VM

CSBAPRY阿里巴巴云原生

• Collector

Collector 作为 OpenCensus 的重要组成部分,由 Go 语言便编写,可以从任何可用 Receivers 的应用中接受流量,而不用关注编程语言以及部署方式,而这个好处显而易见。对于提供 Metrics 和 Trace 的服务或应用而言,只需要一个 Exporters 导出组件,就能从多语言应用中获取数据。

OPENCENSUS

JAEGER/ZIPKIN

PROMETHEUS / STATSD

OPENCENSUS

JAEGER

JAEGER/ZIPKIN

PROMETHEUS

PROMETHEUS/STATSD

ZIPKIN

OPENCENSUS AGENT

(AGENT)

JAEGER

OPENCENSUS

OPENCENSUS

COLLECTOR

PROMETHEUS

JAEGER/ZIPKIN

ZIPKIN

PROMETHEUS/STATSD

OPENCENSUS AGENT

(SIDECAR)

OPENCENSUS

COLLECTOR

HOST

OPENCENSUS

DATADOG

JAEGER/ZIPKIN

OMNITION

PROMETHEUS/STATSD

STACKDRIVER

OPENCENSUS AGENT

(DAEMONSET)

CSDN@阿里巴巴云原生

• Exporters

OpenCensus 可以通过各种 Exporter 实现将相关数据上传到各种后端,比如:Prometheus for stats、OpenZipkin for traces、Stackdriver Monitoring for stats and Trace for traces、Jaeger for traces、Graphite for stats。

OpenCensus与OpenTracing

在上述的项目中有两个项目较为特殊:其一是OpenTracing,他制定了一套无关平台的统一的Trace的标准,后续的很多项目例如Jaeger等都是基于此协议,因此他在当时的Trace标准领域具有不小影响力;其二是OpenCensus,他背靠Google,并且它不仅仅实现了Trace,还包括了Metrics,并且他包含了一系列诸如Agent和Collector的方案,可以说是相当完备。

在当时这两大流派可以说是互相有一大票的追随者,一边是以Google和微软领衔的OpenCensus,一边是众多开源项目和厂商使用的OpenTracing,两者可以说是各有优劣,各领风骚。

我们先看看一个典型服务问题排查过程是怎样的:

• 通过各式各样预设报警发现异常(Metrics/Logs)

• 打开监控大盘查找异常现象,并通过查询找到异常模块(Metrics)

• 对异常模块以及关联日志进行查询分析,找到核心的报错信息(Logs)

• 通过详细的调用链数据定位到引起问题的代码(Tracing)

为了能够获得更好的可观测性或快速解决上述问题,Tracing、Metrics、Logs缺一不可。

LOW

REQUEST-SCOPED METRICS

VOLUME

METRICS

AGGREGATABLE

TRACING

AGGREGATABLE EVENTS

E.G. ROLLUPS

REQUEST

SCOPED

REQUEST-SCOPED

LOGGING

AGGREGATABLE EVENTS

HIGH

EVENTS

REQUEST-SCOPED EVENTS

VOLUME

CSDN@阿里巴巴云原生

与此同时,行业中已经有了丰富的开源及商业方案,其中包括:

• Metric:Zabbix、Nagios、Prometheus、InfluxDB、OpenFalcon、OpenCensus

• Tracing:Jaeger、Zipkin、SkyWalking、OpenTracing、OpenCensus

• Logs:ELK、Splunk、SumoLogic、Loki、Loggly。

Opentelemetry

为了更好的将 Traces、Metrics 和 Logs 融合在一起,OpenTelemetry 诞生了。作为 CNCF 的孵化项目,OpenTelemetry 由 OpenTracing 和 OpenCensus 项目合并而成,是一组规范、API 接口、SDK、工具和集成。为众多开发人员带来 Metrics、Tracing、Logs 的统一标准,三者都有相同的元数据结构,可以轻松实现互相关联。

@稀士掘金技术社区

OPENTELEMETRY

@稀土掘金技术社区

Opentelemetry可以说是含着金汤匙出生:OpenTracing支持,OpenCensus支持,刚开始就自带经验丰富的的社区人员,同时背后也有互联网巨头的支持。

OpenTelemetry 与厂商、平台无关,不提供与可观测性相关的后端服务。可根据用户需求将可观测类数据导出到存储、查询、可视化等不同后端,如 Prometheus、Jaeger 、云厂商服务中。

优势

OpenTelemetry 核心优势集中在以下部分:

• 规范的制定和协议的统一

OpenTelemetry 采用基于标准的实现方法。对标准的关注对于 OpenTelemetry 来说尤其重要,因为需要追踪跨语言的互操作性。许多语言都带有类型定义,可以在实现中使用,例如用于创建可重用组件的接口。包括可观测客户端内部实现所需要的规范,以及可观测客户端与外部通信所需实现的协议规范。具体包括:

• API:定义 Metrics、Tracing、Logs 数据的类型和操作。

• SDK:定义 API 特定语言实现需求,定义配置、数据处理和导出概念。

• 数据:定义 OpenTelemetry Line Protocol (OTLP)。虽然在 Opentelemetry中组件支持了 Zipkin v2 或 Jaeger Thrift 协议格式的实现,但都以第三方贡献库形式提供。只有 OTLP 是 Opentelemetry 官方原生支持的格式。

OPEN TELEMETRY API

SEMANTIC

CONTEXT

TRACER

METER

CONVENTIONS

API

API

API

METER

SHARED CONTEXT

TRACER

PROPAGATOR

INSTRUMENT

SPAN

SPAN

PROCESSOR

PROCESSOR

AGGREGATOR

METRICREADER

SPAN

SPAN

METRIC

METRIC

EXPORTER

OPEN TELEMETRY SDK

EXPORTER

EXPORTER

EXPORTER

OPEN TELEMETRY

COLLECTOR

EXTENSION POINT

SPAN

METRIC

EXPORTER

EXPORTER

VENDOR INGEST

CSDN@阿里巴巴云原生

多语言 SDK 的实现和集成

OpenTelemetry 为每个常见语言都实现了对应 SDK,将导出器与 API 结合在一起。SDK 是具体的、可执行的 API 实现。包含 C++、.NET、Erlang/Elixir、Go、Java、JavaScript、PHP、Python、Ruby、Rust、Swift。

OpenTelemetry SDK 通过使用 OpenTelemetry API 使用选择的语言生成可观测数据,并将该数据导出到后端。并允许为公共库或框架增强。用户可以使用 SDK 进行代码自动注入和手动埋点,同时对其他三方库(Log4j、LogBack 等)集成支持;这些包一般都是根据 opentelemetry-specification 里面的规范与定义,结合语言自身的特点去实现在客户端采集可观测数据的基本能力。如元数据在服务间、进程间的传递,Trace 添加监测与数据导出,Metrics 指标的创建、使用及数据导出等。

数据收集系统的实现

在 Tracing 实践中有个基本原则,可观测数据收集过程需要与业务逻辑处理正交。尽量减少可观测客户端对原有业务逻辑的影响,Collector 是基于这个原则。OpenTelemetry 基于 OpenCensus Service 的收集系统,包括 Agent 和 Collector。Collector 涵盖采集(Collect)、转换(Transform)和导出(Export)可观测数据的功能,支持以多种格式(例如 OTLP、Jaeger、Prometheus 等)接收可观测数据,并将数据发送到一个或多个后端。它还支持在输出可观测数据之前,对其进行处理和过滤。Collector contrib 软件包支持更多数据格式和后端。

从架构层面来说,Collector 有两种模式。一种是把 Collector 部署在应用相同的主机内(如Kubernetes 的 DaemonSet),或者部署在应用相同的 Pod 里面(如Kubernetes 中的 Sidecar),应用采集到的遥测数据,直接通过回环网络传递给 Collector。这种模式统称为 Agent 模式。另一种模式是把 Collector 当作一个独立的中间件,应用把采集到的遥测数据往这个中间件里面传递。这种模式称之为 Gateway 模式。两种模式既可以单独使用,也可以组合使用,只需要数据出口的数据协议格式跟数据入口的数据协议格式保持一致。

SigNoz

OpenTelemetry源自OpenSencuc和OpenTracing的合并,它的目标是集成Trace,Metrics,Logging能力来提供可观测性。过去的分布式追踪往往是各做各的,没有固定的标准,各个分布式追踪方案各显神通,使用不同的协议,不同的标准。但是OpenTelemetry不同,它提供了一系列的标准, 是一个与供应商无关的仪器库。它提供了一组工具、API 和 SDK 来创建和管理遥测数据(Trace,Metrics,Logging)。所以我们更倾向选择原生支持 OpenTelemetry 协议的工具。而目前火热的 SigNoz 就是一个好的选择。

SigNoz 是一个全栈开源应用程序性能监控和可观察性工具,旨在原生支持 OpenTelemetry。它还提供了一个快速的 OLAP 数据库——ClickHouse 作为存储后端。带有开箱即用的应用程序指标图表。

compare

SigNoz vs Prometheus

Prometheus is good if you want to do just metrics. But if you want to have a seamless experience between metrics and traces, then current experience of stitching together Prometheus & Jaeger is not great.

Our goal is to provide an integrated UI between metrics & traces - similar to what SaaS vendors like Datadog provides - and give advanced filtering and aggregation over traces, something which Jaeger currently lack.

SigNoz vs Jaeger

Jaeger only does distributed tracing. SigNoz supports metrics, traces and logs - all the 3 pillars of observability.

Moreover, SigNoz has few more advanced features wrt Jaeger:

Jaegar UI doesn’t show any metrics on traces or on filtered traces

Jaeger can’t get aggregates on filtered traces. For example, p99 latency of requests which have tag - customer_type='premium'. This can be done easily on SigNoz

SigNoz vs Elastic

SigNoz Logs management are based on ClickHouse, a columnar OLAP datastore which makes aggregate log analytics queries much more efficient

50% lower resource requirement compared to Elastic during ingestion

We have published benchmarks comparing Elastic with SigNoz. Check it out here

SigNoz vs Loki

SigNoz supports aggregations on high-cardinality data over a huge volume while loki doesn’t.

SigNoz supports indexes over high cardinality data and has no limitations on the number of indexes, while Loki reaches max streams with a few indexes added to it.

Searching over a huge volume of data is difficult and slow in Loki compared to SigNoz

We have published benchmarks comparing Loki with SigNoz. Check it out here

实践

Trace

无需改动代码,只要启动应用的时候加个代理就可以把全链路的数据传进Signoz里了。

java -javaagent:/agent/opentelemetry-javaagent.jar \
-Dotel.logs.exporter=otlp \
-Dotel.exporter.otlp.endpoint=http://172.34.91.29:4317 \
-Dotel.resource.attributes=service.name=service-provider \
-jar service-provider.jar

Logging

  1. 这一块需要侵入应用程序,opentelemetry 使用 jaeger 生成 traceId,并可以和 logback 集成,通过 logback 的 mdc 注入到日志文件中。

          <dependency>
            <groupId>io.opentelemetry.instrumentation</groupId>
            <artifactId>opentelemetry-spring-boot-starter</artifactId>
            <version>1.22.1-alpha</version>
        </dependency>
        <dependency>
            <groupId>io.opentelemetry.instrumentation</groupId>
            <artifactId>opentelemetry-jaeger-spring-boot-starter</artifactId>
            <version>1.22.1-alpha</version>
        </dependency>
        <dependency>
            <groupId>io.opentelemetry.instrumentation</groupId>
            <artifactId>opentelemetry-logback-mdc-1.0</artifactId>
            <version>1.22.1-alpha</version>
        </dependency>

2、需要把我们的日志文件,导入到 Signoz 里。

Collecting Application Logs from Log file | SigNoz

Metrics

Send Metrics to SigNoz | SigNoz

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

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

相关文章

windows 服务程序和桌面程序集成(一)

本系列文章介绍如何将windows服务程序和桌面程序集成在一起&#xff0c;也就是说一个EXE程序&#xff0c;既可以作为服务程序运行&#xff0c;也可以作为桌面程序运行的双模程序。在十几年前&#xff0c;曾经给客户开发一套C/S架构的出单程序&#xff0c;当时不是很清楚windows…

C++016-C++结构体

文章目录C016-C结构体结构体目标结构体定义结构体实例化结构体题目描述在线练习&#xff1a;总结C016-C结构体 在线练习&#xff1a; http://noi.openjudge.cn/ https://www.luogu.com.cn/ 结构体 参考&#xff1a;https://www.cnblogs.com/ybqjymy/p/16561657.html https://…

【Day1】一小时入门 python 基础,从安装到入门

文章目录python安装安装python安装 pycharmpython基础输出注释变量输入类型转换运算符自增字符串相关操作比较运算符逻辑运算符条件控制while循环list 列表for 循环range函数元组python 安装 安装python 官网进行下载&#xff1a;官网下载地址这里下载的一直是最新版本的 点…

嵌入式linux必备内存泄露检测神器

Valgrind介绍 Valgrind是一个可移植的动态二进制分析工具集&#xff0c;主要用于发现程序中的内存泄漏、不合法内存访问、使用未初始化的内存、不正确的内存释放以及性能问题等&#xff0c;可在Linux和Mac OS X等平台上使用。 Valgrind由多个工具组成&#xff0c;其中最常用的…

Linux操作系统学习(文件缓冲区)

文章目录缓冲区fork后的缓冲区缓冲区 什么是缓冲区&#xff1f; ​ 缓冲区(Buffer&#xff09;就是在内存中预留指定大小的存储空间用来对输入/输出(I/O)的数据作临时存储&#xff0c;这部分预留的内存空间就叫做缓冲区。 缓冲区分为内核缓冲区和用户缓冲区 ​ 内核缓冲区是…

【Linux】P2 vi/vim 编辑器

vim编辑器vim 编辑器介绍vim 三种工作模式vi/vim 操作打开/创建文件命令模式快捷指令底线模式快捷指令前言 上节内容&#xff1a; Linux 基本命令 链接&#xff1a; https://blog.csdn.net/weixin_43098506/article/details/129298221 本节内容&#xff1a; Linux vi 编辑器。 …

STM32 10个工程篇:1.IAP远程升级(一)

清晨一大早起来开始撰写STM32 10个例程篇的第一章即串口IAP远程升级&#xff0c;虽然网络上有很多免费和付费的STM32教程&#xff0c;但是仍然不断地说服自己沉住气、静下心写一份独一无二的&#xff0c;这份独一无二中也凝聚了一名MCU工程师5年间不断地项目迭代积累&#xff0…

总结磁共振成像的脑龄预测的人工智能模型

脑龄预测的人工智能模型 介绍基于神经影像的BA预测BA预测建模:从统计方法到DL统计方法使用统计/最大似然估计方法的BA研究的主要结果深度学习使用DL方法进行BA研究的主要结果可解释的人工智能(即可解释的深度学习方案)可解释的能力(Interpretability,)、可因果性和可解释性…

剑指 Offer —— 数组和字符串

文章目录剑指 Offer 04. 二维数组中的查找代码实现解题方案 思路算法步骤剑指 Offer 05. 替换空格题目描述代码实现解题方案 思路算法步骤剑指 Offer 11. 旋转数组的最小数字 - 解决方案题目描述代码实现剑指 Offer 04. 二维数组中的查找 在一个 n * m 的二维数组中&#xf…

csdn写文章自定义表格怎么做

前言 CSDN写文章时&#xff0c;经常会用到表格&#xff0c;不同于Word文档中直接插入表格&#xff08;自定义几行几列&#xff09;&#xff0c;使用CSDN自带的md文本编辑器时&#xff0c;很难快速插入想要的表格样式&#xff0c;追究原因&#xff0c;也是因为md的语法问题&…

C语言刷题(4)——“C”

各位CSDN的uu们你们好呀&#xff0c;今天小雅兰的内容又到了我们的复习啦&#xff0c;那么还是刷题噢&#xff0c;话不多说&#xff0c;让我们进入C语言的世界吧 BC55 简单计算器 BC56 线段图案 BC57 正方形图案 BC58 直角三角形图案 BC59 翻转直角三角形图案 BC60 带空格…

Python计算分类问题的评价指标(准确率、精确度、召回率和F1值,Kappa指标)

机器学习的分类问题常用评论指标有&#xff1a;准确率、精确度、召回率和F1值&#xff0c;还有kappa指标 。 每次调包去找他们的计算代码很麻烦&#xff0c;所以这里一次性定义一个函数&#xff0c;直接计算所有的评价指标。 每次输入预测值和真实值就可以得到上面的指标值&a…

Camtasia2023电脑屏幕录像视频编辑录屏软件

Camtasia是一款专业的录屏软件&#xff0c;由TechSmith开发。它旨在帮助用户创建高质量的视频内容&#xff0c;包括演示、培训视频、演讲录像、教程等等。 Camtasia适合于需要制作视频教程、软件演示、游戏录像等内容的个人和企业用户。例如&#xff0c;软件开发人员可以使用它…

JUC并发编程与源码分析笔记10-聊聊ThreadLocal

ThreadLocal简介 恶心的大厂面试题 ThreadLocal中ThreadLocalMap的数据结构和关系ThreadLocal的key是弱引用&#xff0c;这是为什么ThreadLocal内存泄漏问题你知道吗ThreadLocal中最后为什么要加remove方法 是什么 ThreadLocal提供线程局部变量。这些变量与正常的变量不同&…

基于神经辐射场(Neural Radiance Fileds, NeRF)的三维重建- 简介(1)

Nerf简介 Nerf&#xff08;neural Radiance Fileds&#xff09; 为2020年ICCV上提出的一个基于隐式表达的三维重建方法&#xff0c;使用2D的 Posed Imageds 来生成&#xff08;表达&#xff09;复杂的三维场景。现在越来越多的研究人员开始关注这个潜力巨大的领域&#xff0c;也…

十大排序(C++版)

测试排序的题目&#xff1a; 912. 排序数组 - 力扣&#xff08;LeetCode&#xff09; 堕落的做法&#xff1a; class Solution { public:vector<int> sortArray(vector<int>& nums) {sort(nums.begin(),nums.end());return nums;} };视频推荐&#xff1a; …

洛谷:P1554 梦中的统计 JAVA

思路&#xff1a;定义一个长度为10的数组&#xff0c;数组下标代表数组元素的数字&#xff0c;比如arr[0]代表数字0.用一个for循环&#xff0c;对每个数先取余再取整&#xff0c;知道取整得到的数为0&#xff0c;说明该数字已经被拆解完了。今天又学了一个输入&#xff0c;原来…

2020蓝桥杯真题美丽的2(填空题) C语言/C++

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 小蓝特别喜欢 2&#xff0c;今年是公元 2020 年&#xff0c;他特别高兴。 他很好奇&#xff0c;在公元 1 年到公元 2020 年&#xff08;包含&#xff09;中&#xff…

论文投稿指南——中文核心期刊推荐(电影、电视艺术)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…

73. python第三方库安装教程(超详细)

73. python第三方库安装教程&#xff08;超详细&#xff09; 文章目录73. python第三方库安装教程&#xff08;超详细&#xff09;1.知识回顾2. openpyxl 库的作用3. 第三方库的安装步骤【警告内容释义】4. 更新pip5. pip 常用命令1. 什么是pip2. pip --version 查看 pip 版本和…