滴滴夜莺基本使用

资料地址:夜莺介绍 - 夜莺云原生监控

前言:

使用滴滴夜莺监控,从安装角度来看,核心模块分为:夜莺(webapi+server),mysql,redis,prometheus,categraf,ibex。由于夜莺及categraf采用go语言开发,学习难度较大,好在本身功能简单,掌握起来不算困难,难点在于prometheus的PromQL,与常规查询数据库查询sql天差地别,但是在监控各个指标上又无处不在,因此,如果对prometheus的PromQL一点都不了解或了解不多的话,就算用了夜莺监控,可能也看不懂大部分监控项监控的是什么

一 概述

夜莺监控( Nightingale )是一款国产、开源云原生监控分析系统,采用 All-In-One 的设计,集数据采集、可视化、监控告警、数据分析于一体。于 2020 年 3 月 20 日,在 github 上发布 v1 版本,已累计迭代 60 多个版本。从 v5 版本开始与 Prometheus、VictoriaMetrics、Grafana、Telegraf、Datadog 等生态紧密协同集成,提供开箱即用的企业级监控分析和告警能力,已有众多企业选择将 Prometheus + AlertManager + Grafana 的组合方案升级为使用夜莺监控。夜莺监控,由滴滴开发和开源,并于 2022 年 5 月 11 日,捐赠予中国计算机学会开源发展委员会(CCF ODC),为 CCF ODC 成立后接受捐赠的第一个开源项目。夜莺监控的核心开发团队,也是Open-Falcon项目原核心研发人员。

1.1 系统架构

夜莺 v5 的设计非常简单,核心是 server 和 webapi 两个模块,webapi 无状态,放到中心端,承接前端请求,将用户配置写入数据库;server 是告警引擎和数据转发模块,一般随着时序库走,一个时序库就对应一套 server,每套 server 可以只用一个实例,也可以多个实例组成集群,server 可以接收 Categraf、Telegraf、Grafana-Agent、Datadog-Agent、Falcon-Plugins 上报的数据,写入后端时序库,周期性从数据库同步告警规则,然后查询时序库做告警判断。每套 server 依赖一个 redis。

二 安装部署

2.1 服务端组件部署

首先我们来看下面的架构图,夜莺的服务端有两个模块:n9e-webapi 和 n9e-server,n9e-webapi 用于提供 API 给前端 JavaScript 使用,n9e-server 的职责是告警引擎和数据转发器。依赖的组件有 MySQL、Redis、时序库,时序库我们这里使用 Prometheus。

2.2 组件安装

mysql和redis现有服务器已经存在,安装步骤在此略过,由于组件之间相互依赖,以下组件安装顺序最好按顺序执行,以免发生意外错误

2.2.1 安装prometheus(时序库)

下载地址:https://s3-gz01.didistatic.com/n9e-pub/prome/prometheus-2.28.0.linux-amd64.tar.gz

指定端口:--web.listen-address=:9191,默认端口9090

# install prometheus
mkdir -p /opt/prometheus
wget https://s3-gz01.didistatic.com/n9e-pub/prome/prometheus-2.28.0.linux-amd64.tar.gz -O prometheus-2.28.0.linux-amd64.tar.gz
tar xf prometheus-2.28.0.linux-amd64.tar.gz
cp -far prometheus-2.28.0.linux-amd64/*  /opt/prometheus/

# service 
cat <<EOF >/etc/systemd/system/prometheus.service
[Unit]
Description="prometheus"
Documentation=https://prometheus.io/
After=network.target

[Service]
Type=simple

ExecStart=/opt/prometheus/prometheus  --config.file=/opt/prometheus/prometheus.yml --web.listen-address=:9191 --storage.tsdb.path=/opt/prometheus/data --web.enable-lifecycle --enable-feature=remote-write-receiver --query.lookback-delta=2m 

Restart=on-failure
SuccessExitStatus=0
LimitNOFILE=65536
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=prometheus


[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable prometheus
systemctl restart prometheus
systemctl status prometheus

# 停止服务
systemctl stop prometheus
# 查看日志
journalctl -f -u prometheus

安装成功之后,可以ip+端口测试安装是否成功,无需账号密码直接进入prometheus首页

例如我的访问路径:35.1.1.193:9191

2.2.2 安装夜莺

下载地址:Releases · ccfos/nightingale · GitHub

下载好安装包后,解压即可

初始化sql文件在解压后的docker文件夹下的initsql文件夹内,执行a-n9e.sql即可

两种启动方式,一种是nohup,一种是systemctl,生产环境建议使用systemctl

mkdir -p /opt/n9e && cd /opt/n9e

# 去 https://github.com/didi/nightingale/releases 找最新版本的包,文档里的包地址可能已经不是最新的了
tarball=n9e-v5.14.1-linux-amd64.tar.gz
urlpath=https://github.com/didi/nightingale/releases/download/v5.14.1/${tarball}
wget $urlpath || exit 1

tar zxvf ${tarball}
# 解压之后,修改/opt/n9e/etc下的配置文件server.conf和webapi.conf
# server.conf修改redis、DB、reader三处
[Redis]
Address = "35.1.1.193:6379"
Password = "Hylink2014@redis"
DB = 15
[DB]
DSN = "root:Hylink2014@mysql@tcp(35.1.1.193:6379)/n9e_v5?charset=utf8mb4&parseTime=True&loc=Local&allowNativePassword=true"
DBType = "mysql"
[Reader]
Url = "http://35.1.1.193:9191"
# webapi.conf修改redis、DB、Clusters三处
[Redis]
Address = "35.1.1.193:6379"
Password = "Hylink2014@redis"
DB = 15
[DB]
DSN = "root:Hylink2014@mysql@tcp(35.1.1.193:6379)/n9e_v5?charset=utf8mb4&parseTime=True&loc=Local&allowNativePassword=true"
DBType = "mysql"
[Clusters]
Prom = "http://35.1.1.193:9191"

nohup ./n9e server &> server.log &
nohup ./n9e webapi &> webapi.log &

# check logs
# check port

===================================分割线========================================
# 制作systemctl启动文件
# nsever:
cat <<EOF >/etc/systemd/system/n9e-server.service
[Unit]
Description="n9e-server"
After=network.target

[Service]
Type=simple

ExecStart=/opt/n9e/n9e server
WorkingDirectory=/opt/n9e

Restart=on-failure
SuccessExitStatus=0
LimitNOFILE=65536
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=n9e-server


[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable n9e-server
systemctl restart n9e-server
systemctl status n9e-server


systemctl stop n9e-server
# 查看日志
journalctl -f -u n9e-server
===================================分割线========================================
# nwebapi: 
cat <<EOF >/etc/systemd/system/n9e-webapi.service
[Unit]
Description="n9e-webapi"
After=network.target

[Service]
Type=simple

ExecStart=/opt/n9e/n9e webapi
WorkingDirectory=/opt/n9e

Restart=on-failure
SuccessExitStatus=0
LimitNOFILE=65536
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=n9e-webapi


[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable n9e-webapi
systemctl restart n9e-webapi
systemctl status n9e-webapi

systemctl stop n9e-webapi
# 查看日志
journalctl -f -u n9e-webapi

安装成功之后,ip+端口访问即可

例如:35.1.1.193:18000,默认账号:root,默认密码:root.2020,登录成功之后自行修改,在执行初始化sql文件的时候,也可以发现账号密码是初始化的时候执行的

2.2.3 安装ibex(告警自愈)

Ibex 是告警自愈功能依赖的模块,提供一个批量执行命令的通道,可以做到在告警的时候自动去目标机器执行脚本,如果大家没有此需求,可以略过本章节

下载地址:GitHub - flashcatcloud/ibex

下载安装包之后,解压缩,在 etc 下可以找到服务端和客户端的配置文件,在 sql 目录下可以找到初始化 sql 脚本。优先初始化sql,再启动服务

mkdir -p /opt/ibex && cd /opt/ibex
tar zxvf /home/hylink/docker/container/ibex/package/ibex-1.0.0.tar.gz

启动agentd 
客户端的配置非常非常简单,agentd.conf 内容如下:
# debug, release
RunMode = "release"

# task meta storage dir
MetaDir = "./meta"

[Heartbeat]
# unit: ms
Interval = 1000
# rpc servers
Servers = ["35.1.1.193:20090"]
# $ip or $hostname or specified string
Host = "$hostname-$ip"


下面是启动 ibex-agentd 的命令:
nohup ./ibex agentd &> agentd.log &

===================================分割线===================================
制作systemctl启动
agentd:
# service 
cat <<EOF >/etc/systemd/system/ibex-agentd.service
[Unit]
Description="ibex-agentd"
After=network.target

[Service]
Type=simple

ExecStart=/opt/ibex/ibex agentd
WorkingDirectory=/opt/ibex

Restart=on-failure
SuccessExitStatus=0
LimitNOFILE=65536
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=ibex-agentd


[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable ibex-agentd
systemctl restart ibex-agentd
systemctl status ibex-agentd


systemctl stop ibex-agentd
# 查看日志
journalctl -f -u ibex-agentd

===================================分割线===================================
server:
# service 
cat <<EOF >/etc/systemd/system/ibex-server.service
[Unit]
Description="ibex-server"
After=network.target

[Service]
Type=simple

ExecStart=/opt/ibex/ibex server
WorkingDirectory=/opt/ibex

Restart=on-failure
SuccessExitStatus=0
LimitNOFILE=65536
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=ibex-server


[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable ibex-server
systemctl restart ibex-server
systemctl status ibex-server


systemctl stop ibex-server
# 查看日志
journalctl -f -u ibex-server

2.2.4 安装categraf(采集器)

Categraf 是一款 all-in-one 的采集器,由 快猫团队 开源。

Categraf 不但可以采集 OS、MySQL、Redis、Oracle 等常见的监控对象,也准备提供日志采集能力和 trace 接收能力,这是夜莺主推的采集器,相关信息请查阅项目 README

下载地址:GitHub - flashcatcloud/categraf: one-stop telemetry collector for nightingale

修改categraf/conf下的config.toml配置文件如下

可选修改项:hostname,可根据注释修改,也可以自定义

mkdir -p /opt/categraf
tar -xzvf /home/hylink/docker/container/categraf/package/categraf-v0.2.18-linux-amd64-with-oracle-plugin.tar.gz
cp -far categraf-v0.2.18-linux-amd64-with-oracle-plugin/*  /opt/categraf/

#找到 
 32 [[writers]]
 33 url = "http://127.0.0.1:19000/prometheus/v1/write"
#修改为:
 32 [[writers]]
 33 url = "http://35.1.1.193:19000/prometheus/v1/write"
 
#启动categraf
nohup /opt/categraf/categraf/categraf &> /opt/categraf/categraf/stdout.log &

====================================分割线=======================================
制作systemctl启动
categraf:
# service 
cat <<EOF >/etc/systemd/system/categraf.service
[Unit]
Description="categraf"
After=network.target

[Service]
Type=simple

ExecStart=/opt/categraf/categraf
WorkingDirectory=/opt/categraf

Restart=on-failure
SuccessExitStatus=0
LimitNOFILE=65536
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=categraf


[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable categraf
systemctl restart categraf
systemctl status categraf


systemctl stop categraf
# 查看日志
journalctl -f -u categraf

三 使用

登录夜莺之后,可以看到大致分为监控对象、监控看图、告警管理、告警自愈、人员组织、系统信息六大模块

3.1 监控对象

监控对象包含了一个对象列表选项卡①,点击对象列表,可以看到右侧展示出一个业务组,默认生成的业务组有未归组对象和Default Busi Group两个选项②,点击业务组右侧齿轮③,可以创建新的业务组,而我们监控的服务器列表在最右侧显示,一般默认划分到未归组对象下,在右上角的批量操作按钮④,可以调整业务组、标签、备注及删除

对于监控列表的服务器信息,每在一台服务器上安装categraf采集器,便会生成一条服务器的监控记录,“标识”列展示的内容可修改,修改方式:

找到categraf的安装地址,在conf文件夹下,找到config.toml文件进行编辑,找到hostname配置项,可根据自己的需要进行修改,也可以直接使用$hostname(服务器名),$ip(服务器ip)

3.2 监控看图

监控看图下又分为即时查询、快捷视图、监控大盘

3.2.1 即时查询

进入即时查询,可以看到右侧展示信息,点击,系统会默认一些查询参数,这些查询参数是由prometheus生成,即PromQL(Prometheus Query Language),具体信息到prometheus官网文档了解:Querying basics | Prometheus

点击进行查询,为数据展示形式:表格(Table)/图表(Graph)

3.2.2 快捷视图

点击快捷视图,即可看到右侧展示信息,系统默认生成一个快捷视图,也可以点击右上角加号进行添加,过滤条件即为默认视图的查询条件,在进行快捷视图创建的时候,可根据自己的需要进行调整,监控指标也是夜莺系统默认生成的,有一个metrics.yaml文件,记录了全部的快捷查询参数,存放在/opt/n9e/etc目录下(参考2.2.2 夜莺安装)

3.2.3 监控大盘

点击监控大盘,即可看到右侧展示信息,此处的业务组与监控对象的业务组为同一业务组,只是此处不展示未归组对象,选中业务组名称,为业务组添加大盘,点击更多操作即可导入监控大盘,根据需要选择不同的导入方式,系统也会默认生成一些大盘模板供人选择,点击大盘名称即可查看大盘监控数据

不同业务组创建的监控大盘相互隔离,categraf源码也提供了一部分的大盘监控及告警json,categraf的代码托管在两个地方:

中国计算学会确实开源平台: https://www.gitlink.org.cn/flashcat/categraf

Github:https://github.com/flashcatcloud/categraf

在源码的inputs文件夹内,存放的是categraf提供的监控插件,alerts为前缀的json文件是告警规则文件,以dashboard为前缀的json文件是监控大盘规则文件,以es为例:

alerts.json为告警规则json

dashboard.json为监控大盘规则json

当准备启用某个监控插件时,进入到categraf的安装目录,找到conf文件夹,只要是以"input."开头的文件夹均为监控大盘的插件,只需要进入到input开头的文件夹内,把.toml配置文件内的相关注释去掉,重启categraf即可启用

categraf提供的监控,以我的理解,提供了比如linux服务器本身,以及mysql、oracle等比较好封装的监控,或者说这些监控,都是从prometheus相关的exporter演化而来,毕竟categraf也算是滴滴开发团队刚刚起步的这么一个项目,如果要监控应用,目前情况也只能我们自己来实现

3.2.3 应用监控

想要监控应用,就得通过埋点处理,最常见的通用埋点工具有两个,一个是 statsd,一个是 prometheus SDK,当然,各个语言也会有自己的更方便的方式,比如 Java 生态使用 micrometer 较多,如果是 SpringBoot 的程序,则使用 actuator 会更便捷,actuator 底层就是使用 micrometer。

这里我们采用springboot+actuator的方式进行埋点,具体步骤如下:

3.2.3.1 添加maven依赖

阿里maven仓库地址:仓库服务

maven官方仓库地址:https://mvnrepository.com/

这里强调一下,网上大部分提供的资料只告诉我们添加了actuator和prometheus的依赖,但是由于项目中依赖的jar包过多,搞不好就会有jar包冲突的情况发生,而且在调试的过程中发现,actuator和prometheus对jar包版本要求相对严格,因此在使用的过程中要尤其注意

以现有的执法监督服务为例,添加如下maven依赖:

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>

		<dependency>
			<groupId>io.micrometer</groupId>
			<artifactId>micrometer-registry-prometheus</artifactId>
		</dependency>

启动类添加如下代码:

package com.example.prometheus;

import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class PrometheusApplication {

	public static void main(String[] args) {
		SpringApplication.run(PrometheusApplication.class, args);
	}

	/**
	 * 新增代码
	 * @param applicationName
	 * @return
	 */
	@Bean
	MeterRegistryCustomizer<MeterRegistry> configurer(@Value("${spring.application.name}") String applicationName){
		return (registry -> registry.config().commonTags("application", applicationName));
	}
}

配置文件新增如下代码与spring平级:

management:
  endpoints:
    web:
      exposure:
        include: '*'
  metrics:
    tags:
      application: ${spring.application.name}

启动服务测试,如果没有发生异常,则到此配置结束

以下是我遇到的异常:

异常一:

原因:缺少jar包,引入maven依赖

		<dependency>
			<groupId>io.prometheus</groupId>
			<artifactId>simpleclient_common</artifactId>
    	<version>0.9.0</version>
		</dependency>

异常二:

原因:jar包版本不对,引入正确的jar包版本

		<dependency>
			<groupId>io.prometheus</groupId>
			<artifactId>simpleclient_common</artifactId>
    	<version>0.12.0</version>
		</dependency>

分析:

因为执法监督服务的springboot版本为2.6.4,所以默认引入actuator的版本为2.6.4,prometheus的版本为1.8.3,对应的simpleclient_common版本为0.12.0

验证:

输入下面地址,ip+当前服务端口

http://localhost:8080/actuator/prometheus

如果配置没问题,则会看到如下信息

这些信息就是prometheus提供的监控信息,接下来就是如何让prometheus采集到这些信息,然后通过夜莺来浏览这些监控数据

3.2.3.2 prometheus配置文件修改

找到prometheus的安装目录,修改prometheus.yml文件,在scrape_configs参考原有的配置项,新增如下配置:

- job_name: 项目名
  # 抓取端点
  metrics_path: '/actuator/prometheus'
  # 抓取频率
  scrape_interval: 5s
  static_configs:
  # 目标机器
  - targets: ['ip+端口']

重启prometheus使配置项生效

3.2.3.3 查看数据

可以看到我们监控的应用名以及应用地址等信息已经被监测到了

3.3 告警管理

3.3.1 告警规则

点击告警规则①,右侧为展示信息,业务组还是同一个业务组,列表③则为告警规则,可手动添加,也可更多操作来导入告警规则,系统会默认生成一些常规告警规则直接导入使用,也可以导入符合规格的json数据生成告警规则,点击告警规则名称,可进入具体的告警规则查看详细信息

这里着重说以下两点:

3.3.1.1 PromQL

告警规则核心

3.3.1.2 通知配置

此处的通知媒介下所列出的选项,以及选项背后的参数,是可以手动修改的,具体修改步骤如下:

3.3.1.2.1 路径

找到配置文件的路径,在夜莺(n9e)安装目录下,找到etc文件夹,即可看到server.conf以及webapi.conf两个配置文件

3.3.1.2.2 webapi.conf

打开文件,找到[[NotifyChannels]]标签,就可以看到上图我们配置的通知媒介,根据自己的需要进行取舍,此处用来页面展示

3.3.1.2.3 server.conf

对于邮件方式的告警通知,只需要修改该文件内[STMP]项下的相关参数配置即可。对于其他方式的告警通知,可参考官方文档

3.3.2 记录规则

官方暂无文档说明

3.3.3 屏蔽规则

屏蔽规则,是针对告警事件的,大家在生成的告警事件中可以看到每个事件有很多标签,屏蔽规则就是针对这些标签配置过滤规则,满足过滤规则的,就不生成告警事件了。

比如,我想屏蔽所有设备失联的告警,把标签key配置为:__name__,运算符:==,标签value:target_up即可。运算符=~表示正则,针对标签value,可以填写正则表达式,匹配一批的告警事件。运算符in表示数组包含的关系,即value可以配置多个。

资料地址:功能介绍 - 屏蔽规则 - 《夜莺(Nightingale)v5.1 使用手册》 - 书栈网 · BookStack

3.3.4 订阅规则

某个告警除了某个组的人关心,可能其他人也关心,就配置订阅规则,比如K8S平台的运维人员要作为告警接收人来接收所有K8S的告警,但是K8S的一些重大网络故障会影响整个K8S集群上面的业务方,上层业务也会关心这类告警,此时业务方就可以订阅K8S集群的部分重大告警。

对于订阅规则,还有一种场景,比如运维团队管理了公司所有的告警规则,比如内存利用率的告警,不同业务线的人只关心自己的,那不同业务线的人就可以通过订阅规则,只订阅自己业务线的机器的告警。只需简单的为这批机器打上业务线标签,就可以通过这些标签做过滤。

当然,有的公司推行DevOps文化,自己的狗粮自己吃,自己的服务自己运维,我这个业务线关心哪些告警,就自己创建一个业务组,配置相关策略,跟别的业务线没有任何关系,也不需要由特定的某个团队帮我配置,这样也是可以的,不同公司文化不同,组织架构职能分工不同,大家就根据自己的公司情况来规划即可。

不过,从性能上讲,建议多使用订阅规则,让整体的告警规则变少,因为告警规则每次判断,都要查询时序库,如果告警规则量很大,对时序库的压力是很大的。当然,对性能的影响也没有那么夸张,把这个信息透传给大家,大家自行把握就好。

资料地址:功能介绍 - 订阅规则 - 《夜莺(Nightingale)v5.1 使用手册》 - 书栈网 · BookStack

3.3.5 活跃告警

列出了当前所有的未恢复活跃告警,如果某个告警恢复了,就会自动从这个列表中删除,这个页面还是蛮重要的,可以作为日常巡检的一项,每天上下班的时候都看一下,看看哪些事件还没恢复,漏了处理。

活跃告警可以删除,这个操作比较危险,一定要弄明白原理。通常情况下,我们是无需手工删除的,比如cpu_usage_idle告警了,会自动创建一条告警事件,当cpu_usage_idle的值恢复了,即这条告警变成恢复状态了,系统就会自动从活跃告警中删除,所以,通常情况下,就让系统自动处理就好了。

资料地址:功能介绍 - 当前告警活跃事件 - 《夜莺(Nightingale)v5.1 使用手册》 - 书栈网 · BookStack

3.3.6 历史告警

相比【活跃告警】,【历史告警】数量更多,会把恢复状态的消息也存档展示,用处不是很大,主要是留档查问题用的,这个表的数量增加会比较快,大家要经常关注一下,如果表的数量很多,比如超过100万,建议做一下清理,量太大的话会影响告警处理的速度,因为每一条告警事件都要往这个表里插入。

3.4 告警自愈

所谓的告警自愈,主要是靠告警规则中配置webhook,即在告警和恢复的时候,自动调用指定的webhook地址,在这个webhook中写自动处理的逻辑。这个功能大部分监控系统都支持,不过对于运维人员,这个门槛可能稍高。夜莺和ibex(类似之前v3版本中的job模块)整合,可以做到告警的时候自动执行某个脚本,运维人员只需要写脚本即可,这个门槛会低一些。

资料地址:功能介绍 - 告警自愈 - 《夜莺(Nightingale)v5.1 使用手册》 - 书栈网 · BookStack

3.4.1 自愈脚本

在这个页面提前准备好一些自愈脚本,python、perl、ruby都行,只要机器上有对应的运行环境,系统会为每个自愈脚本生成一个ID,这个ID后面用于配置到告警规则那里形成联动。

3.4.2 执行历史

保存了所有告警自愈的调用历史,可以查看执行结果,包括脚本的stdout和stderr等

3.5 人员组织

权限范围由大到小排序

业务组→团队→用户

也就是业务组包含团队,团队包含用户

3.5.1 用户管理

角色:

超管(admin)、只读(guest)、普通(standard)

3.5.2 团队管理

可以新建团队,并在相应团队添加相应用户

3.5.3 业务组管理

可以新建业务组,并在相应业务组内添加相应团队

3.6 系统信息

3.6.1 系统版本

查看系统版本

3.6.2 管理员迁移

暂不清楚干嘛的

3.6.3 告警引擎

查看夜莺server服务部署情况

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值