ELK中Logstash的配置和用法

《Elasticsearch搜索引擎系统入门》中简单描述了Logstah的安装,本篇文章将较为详细的讲解Logstash的基本配置和用法。

Logstash介绍

Logstash是一个开源的、服务端的数据处理pipeline(管道),它可以接收多个源的数据、然后对它们进行转换、最终将它们发送到指定类型的目的地。Logstash是通过插件机制实现各种功能的,可以在 https://github.com/logstash-plugins 下载各种功能的插件,也可以自行编写插件。

Logstash实现的功能主要分为接收数据、解析过滤并转换数据、输出数据三个部分,对应的插件依次是input插件、filter插件、output插件,其中,filter插件是可选的,其它两个是必须插件。也就是说 在一个完整的Logstash配置文件中,必须有input插件和output插件

input {
    #输入插件
}
filter {
    #过滤匹配插件
}
output {
    #输出插件
}

简单启动

./bin/logstash -e 'input{stdin{}} output{stdout{codec=>rubydebug}}'

解释下这条命令的含义:

  • -e代表执行的意思。
  • input即输入的意思,input里面即是输入的方式,这里选择了stdin,就是标准输入(从终端输入)。
  • output即输出的意思,output里面是输出的方式,这里选择了stdout,就是标准输出(输出到终端)。
  • 这里的codec是个插件,表明格式。这里放在stdout中,表示输出的格式,rubydebug是专门用来做测试的格式,一般用来在终端输出JSON格式。

在这里插入图片描述

Logstash在输出内容中会给事件添加一些额外信息。比如"@version"、"host"、"@timestamp" 都是新增的字段, 而最重要的是@timestamp ,用来标记事件的发生时间。由于这个字段涉及到Logstash内部流转,如果给一个字符串字段重命名为@timestamp的话,Logstash就会直接报错。另外,也不能删除这个字段。

基本配置

在logstash的输出中,常见的字段还有type,表示事件的唯一类型、tags,表示事件的某方面属性,我们可以随意给事件添加字段或者从事件里删除字段。

使用-e参数在命令行中指定配置是很常用的方式,但是如果logstash需要配置更多规则的话,就必须把配置固化到文件里,这就是logstash事件配置文件,如果把上面在命令行执行的logstash命令,写到一个配置文件logstash-simple.conf中,就变成如下内容:

input { stdin { } 
}
output {
   stdout { codec => rubydebug }
}

这就是最简单的Logstash事件配置文件。此时,可以使用logstash的-f参数来读取配置文件,然后启动logstash进程,操作如下:bin/logstash -f logstash-simple.conf,如果要放到后台启动: nohup bin/logstash -f logstash-simple.conf &

logstash读取文件配置示例

# logstash-demo.conf

input {
        file {
        path => "/var/log/syslog"
    }
}

output {
     stdout {
               codec => rubydebug #这里仍然采用rubydebug的JSON输出格式,这对于调试logstash输出信息是否正常非常有用
          }
}

# 如果需要监控多个文件,可以通过逗号分隔即可,例如:
# path => ["/var/log/*.log","/var/log/message","/var/log/secure"]

在这里插入图片描述

logstash和kafka

这个配置文件中,输入input仍然是file,重点看输出插件,这里定义了output的输出源为kafka,通过bootstrap_servers选项指定了kafka集群的IP地址和端口。特别注意这里IP地址的写法,每个IP地址之间通过逗号分隔。另外,output输出中的topic_id选项,是指定输出到kafka中的哪个topic下,这里是osmessages,如果无此topic,会自动重建topic。

输出到kafka:

input {
        file {
        path => "/var/log/messages"
    }
}
output {
    kafka {
    bootstrap_servers => "172.16.213.51:9092,172.16.213.75:9092,172.16.213.109:9092"
        topic_id => "osmessages"
        }
}

从kafka中读取数据并输出到ES:

input {
        kafka {
        bootstrap_servers => "172.16.213.51:9092,172.16.213.75:9092,172.16.213.109:9092"
        topics => ["osmessages"]
        }
}
output {
        elasticsearch {
        hosts => ["172.16.213.37:9200","172.16.213.77:9200","172.16.213.78:9200"]
        index => " osmessageslog-%{+YYYY-MM-dd}"
        }
}

Logstash的输入插件

input插件主要用于接收数据,Logstash支持接收多种数据源,常用的有如下几种:

  • file: 读取一个文件,这个读取功能有点类似于linux下面的tail命令,一行一行的实时读取。
  • syslog: 监听系统514端口的syslog messages,并使用RFC3164格式进行解析。
  • redis: Logstash可以从redis服务器读取数据,此时redis类似于一个消息缓存组件。
  • kafka:Logstash也可以从kafka集群中读取数据,kafka加Logstash的架构一般用在数据量较大的业务场景,kafka可用作数据的缓冲和存储。
  • filebeat:filebeat是一个文本日志收集器,性能稳定,并且占用系统资源很少,Logstash可以接收filebeat发送过来的数据。

Stdin输入

Stdin输入就是把输入的内容直接输出到控制台,不做存储。配置示例:

input {
	stdin {
	}
}
filter {
}
output {
	stdout {
		codec => rubydebug
	}
}

进入 logstash的安装目录:

mkdir config/input_config/
cd config/input_config/
vim Stdin.conf #然后写入上面的配置内容

再次回到logstash的安装目录:

sudo chmod -R 777 data/
# 使用刚才的配置文件启动
./bin/logstash -r -f ./config/input_config/Stdin.conf

启动后,在控制台输入内容就可以收集到:
在这里插入图片描述

文件内容输入

logstash使用一个名为filewatch的ruby gem库来监听文件变化,并通过一个叫.sincedb的数据库文件来记录被监听的日志文件的读取进度(时间戳),这个sincedb数据文件的默认路径在 logstash/data/plugins/inputs/file下面,文件名类似于.sincedb_0776ae3d702d482a9bdd8900c6550225:
在这里插入图片描述

配置示例:

input {
	file {
		path => "/home/rx/tmp/test.log"
		tags => "123"
		type => "syslog"
	}
}
filter {
}
output {
	stdout {
		codec => rubydebug
	}
}
  • path里面支持日志路径的通配符,比如:/tmp/log*/*.log
  • 这个配置是监听并接收本机的 /home/rx/tmp/test.log 文件内容,start_position表示按时间戳记录的地方开始读取,如果没有时间戳则从头开始读取,有点类似cat命令,默认情况下,logstash会从文件的结束位置开始读取数据,也就是说logstash进程会以类似tail -f命令的形式逐行获取数据。type用来标记事件类型,通常会在输入区域通过type标记事件类型。

将上面的内容保存到 logstash目录下面的 config/input_config/File.conf
然后启动:./bin/logstash -r -f ./config/input_config/File.conf
接下来,给 /home/rx/tmp/test.log 里面写入内容,查看logstash控制台:
在这里插入图片描述

读取TCP网络数据

使用了logstash的TCP/UDP插件读取网络数据,其中5514端口是logstash启动的tcp监听端口。

input {
  tcp {
    port => "5514"
  }
}

filter {
}

output {
    stdout{
        codec=>rubydebug
    }
}

Logstash编码插件(Codec)

其实我们就已经用过编码插件codec了,也就是这个rubydebug,它就是一种codec,虽然它一般只会用在stdout插件中,作为配置测试或者调试的工具。

编码插件(Codec)可以在logstash输入或输出时处理不同类型的数据,因此,Logstash不只是一个 input-->filter-->output的数据流,而是一个input-->decode-->filter-->encode-->output 的数据流。

Codec支持的编码格式常见的有plain、json、json_lines等。下面依次介绍。

codec插件之plain

plain是一个空的解析器,它可以让用户自己指定格式,也就是说输入是什么格式,输出就是什么格式。下面是一个包含plain编码的事件配置文件:

input{
    stdin{
	}
}
output{
    stdout{
        codec => "plain"
	}
}

codec插件之json、json_lines

如果发送给logstash的数据内容为json格式,可以在input字段加入codec=>json来进行解析,这样就可以根据具体内容生成字段,方便分析和储存。如果想让logstash输出为json格式,可以在output字段加入codec=>json,下面是一个包含json编码的事件配置文件:

input {
    stdin {
        }
    }
output {
    stdout {
        codec => json
        }
}

这就是json格式的输出,可以看出,json每个字段是key:values格式,多个字段之间通过逗号分隔。有时候,如果json文件比较长,需要换行的话,那么就要用json_lines编码格式了。

Logstash过滤器插件(Filter)

filter插件主要用于数据的过滤、解析和格式化,也就是将非结构化的数据解析成结构化的、可查询的标准化数据。常见的filter插件有如下几个:

  • grok:grok是Logstash最重要的插件,可解析并结构化任意数据,支持正则表达式,并提供了很多内置的规则和模板可供使用。此插件使用最多,但也最复杂。
  • mutate: 此插件提供了丰富的基础类型数据处理能力。包括类型转换,字符串处理和字段处理等。
  • date:此插件可以用来转换你的日志记录中的时间字符串。
  • GeoIP:此插件可以根据IP地址提供对应的地域信息,包括国别,省市,经纬度等,对于可视化地图和区域统计非常有用。

filter基本配置

配置示例:

input {
	stdin {
	}
}
filter {
	json {
		source => "message"
		target => "content"
	}
}
output {
	stdout {
		codec => rubydebug
	}
}

以上内容 filter 中的 source表示对 message 部分进行解析,target 表示目标字段,可以将 message里面的内容解析出来后放到 content 中。

保存上面配置文件到 Stdin_filter.conf 中,然后运行:./bin/logstash -r -f ./config/input_config/Stdin_filter.conf
在控制台输入一个json,示例:{"ip":"127.0.0.1","method":"POST","url":"/user/info?id=1"}
可以看到 json的内容被解析到了 content 里面,而message 里面是原始的json字符串内容。
在这里插入图片描述

Grok 正则捕获

grok是一个十分强大的logstash filter插件,他可以通过正则解析任意文本,将非结构化日志数据弄成结构化和方便查询的结构。他是目前logstash 中解析非结构化日志数据最好的方式。

Grok 的语法规则是:%{语法: 语义},“语法”指的就是匹配的模式,例如使用NUMBER模式可以匹配出数字,IP模式则会匹配出127.0.0.1这样的IP地址。

例如输入的内容为:

172.16.213.132 [07/Feb/2018:16:24:19 +0800] "GET / HTTP/1.1" 403 5039

那么:
%{IP:clientip} 匹配模式将获得的结果为:clientip: 172.16.213.132
%{HTTPDATE:timestamp} 匹配模式将获得的结果为:timestamp: 07/Feb/2018:16:24:19 +0800
%{QS:referrer} 匹配模式将获得的结果为:referrer: "GET / HTTP/1.1"

下面是一个组合匹配模式,它可以获取上面输入的所有内容:

%{IP:clientip}\ \[%{HTTPDATE:timestamp}\]\ %{QS:referrer}\ %{NUMBER:response}\ %{NUMBER:bytes}	

通过上面这个组合匹配模式,我们将输入的内容分成了五个部分(即五个字段),将输入内容分割为不同的数据字段,这对于日后解析和查询日志数据非常有用,这正是使用grok的目的。

Logstash默认提供了近200个匹配模式(其实就是定义好的正则表达式)让我们来使用,可以在logstash安装目录下 vendor/bundle/jruby/2.5.0/gems/logstash-patterns-core-4.1.2/patterns 目录里面查看,基本定义在grok-patterns文件中。
在这里插入图片描述
在这里插入图片描述

从这些定义好的匹配模式中,可以查到上面使用的四个匹配模式对应的定义规则:

NUMBER		(?:%{BASE10NUM})
HTTPDATE	%{MONTHDAY}/%{MONTH}/%{YEAR}:%{TIME} %{INT}
IP		    (?:%{IPV6}|%{IPV4})
QS		    %{QUOTEDSTRING}

举例说明,写入下面的配置文件

// Grok.conf

input{
    stdin{}
}
filter{
    grok{
        match => ["message","%{IP:clientip}\ \[%{HTTPDATE:timestamp}\]\ %{QS:referrer}\ %{NUMBER:response}\ %{NUMBER:bytes}"]
    }
}
output{
    stdout{
        codec => "rubydebug"
    }
}

启动 ./bin/logstash -r -f ./config/my_config/Grok.conf
输入内容:

127.10.12.13 [30/Aug/2023:16:24:19 +0800] "GET / HTTP/1.1" 403 5039

在这里插入图片描述

可以看到已经对输入的内容按照相应的正则解析到了指定的字段

时间处理(Date)

date插件是对于排序事件和回填旧数据尤其重要,它可以用来转换日志记录中的时间字段,变成LogStash::Timestamp对象,然后转存到@timestamp字段里。下面是date插件的一个配置示例(这里仅仅列出filter部分):

filter {
    grok {
        match => ["message", "%{HTTPDATE:timestamp}"]
    }
    date {
        match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
    }
}

在这里插入图片描述

数据修改(Mutate)

(1)正则表达式替换匹配字段
gsub可以通过正则表达式替换字段中匹配到的值,只对字符串字段有效,下面是一个关于mutate插件中gsub的示例(仅列出filter部分):

//这个示例表示将filed_name_1字段中所有"/"字符替换为"_"。
filter {
    mutate {
        gsub => ["filed_name_1", "/" , "_"]
    }
}

(2)分隔符分割字符串为数组
split可以通过指定的分隔符分割字段中的字符串为数组,下面是一个关于mutate插件中split的示例(仅列出filter部分):

//这个示例表示将filed_name_2字段以"|"为区间分隔为数组。
filter {
    mutate {
        split => ["filed_name_2", "|"]
    }
}

(3)重命名字段
rename可以实现重命名某个字段的功能,下面是一个关于mutate插件中rename的示例(仅列出filter部分):

//这个示例表示将字段old_field重命名为new_field。
filter {
    mutate {
        rename => { "old_field" => "new_field" }
    }
}

(4)删除字段
remove_field可以实现删除某个字段的功能,下面是一个关于mutate插件中remove_field的示例(仅列出filter部分):

//这个示例表示将字段timestamp删除。
filter {
    mutate {
        remove_field  =>  ["timestamp"]
    }
}

综合案例:

input {
    stdin {}
}
filter {
    grok {
        match => { "message" => "%{IP:clientip}\ \[%{HTTPDATE:timestamp}\]\ %{QS:referrer}\ %{NUMBER:response}\ %{NUMBER:bytes}" }
        remove_field => [ "message" ]
   }
date {
        match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
    }
mutate {
           rename => { "response" => "response_new" }
           convert => [ "response","float" ]
           gsub => ["referrer","\"",""]
           remove_field => ["timestamp"]
           split => ["clientip", "."]
        }
}
output {
    stdout {
        codec => "rubydebug"
    }
}

GeoIP 地址查询归类

GeoIP是最常见的免费IP地址归类查询库,当然也有收费版可以使用。GeoIP库可以根据IP 地址提供对应的地域信息,包括国别,省市,经纬度等,此插件对于可视化地图和区域统计非常有用。下面是一个关于GeoIP插件的简单示例(仅列出filter部分):

filter {
    geoip {
        source => "ip_field" //ip_field字段是输出IP地址的一个字段。
    }
}

filter插件综合应用实例

下面给出一个业务系统输出的日志格式,由于业务系统输出的日志格式无法更改,因此就需要我们通过logstash的filter过滤功能以及grok插件来获取需要的数据格式,此业务系统输出的日志内容以及原始格式如下:

2018-02-09T10:57:42+08:00|~|123.87.240.97|~|Mozilla/5.0 (iPhone; CPU iPhone OS 11_2_2 like Mac OS X) AppleWebKit/604.4.7 Version/11.0 Mobile/15C202 Safari/604.1|~|http://m.sina.cn/cm/ads_ck_wap.html|~|1460709836200|~|DF0184266887D0E

可以看出,这段日志都是以 |~| 为区间进行分隔的,那么刚好我们就以 |~| 为区间分隔符,将这段日志内容分割为6个字段。这里通过grok插件进行正则匹配组合就能完成这个功能。

完整的grok正则匹配组合语句如下:

%{TIMESTAMP_ISO8601:localtime}\|\~\|%{IPORHOST:clientip}\|\~\|(%{GREEDYDATA:http_user_agent})\|\~\|(%{DATA:http_referer})\|\~\|%{GREEDYDATA:mediaid}\|\~\|%{GREEDYDATA:osid}

调试grok正则表达式工具:http://grokdebug.herokuapp.com

Logstash的输出插件

output插件用于数据的输出,一个Logstash事件可以穿过多个output,直到所有的output处理完毕,这个事件才算结束。输出插件常见的有如下几种:

  • file:表示将日志数据写入磁盘上的文件。
  • elasticsearch:表示将日志数据发送给Elasticsearch。Elasticsearch可以高效方便和易于查询的保存数据。
  • redis:发送数据到redis中,从这里可以看出,redis插件既可以用在input插件中,也可以用在output插件中。
  • kafka:发送数据到kafka中,与redis插件类似,此插件也可以用在Logstash的输入和输出插件中。
  • graphite:表示将日志数据发送给graphite,graphite是一种流行的开源工具,用于存储和绘制数据指标。此外,Logstash还支持输出到nagios、hdfs、email(发送邮件)和Exec(调用命令执行)。

更多支持的输出方式,可以在 https://www.elastic.co/guide/en/logstash/current/output-plugins.html 查看:
在这里插入图片描述

输出到标准输出(stdout)

stdout与之前介绍过的stdin插件一样,它是最基础和简单的输出插件,主要的功能和用途就是用于调试。下面是一个配置实例:

output {
    stdout {
        codec => rubydebug
    }
}

保存为文件(file)

file插件可以将输出保存到一个文件中,比如下面这个配置中,使用了变量匹配,用于自动匹配时间和主机名,这在实际使用中很有帮助。配置实例如下:

output {
    file {
        path => "/data/log3/%{+yyyy-MM-dd}/%{host}_%{+HH}.log"
    }
}

输出到elasticsearch

Logstash将过滤、分析好的数据输出到elasticsearch中进行存储和查询,是最经常使用的方法。下面是一个配置实例:

output {
    elasticsearch {
        host => ["172.16.213.37:9200","172.16.213.77:9200","172.16.213.78:9200"]
        index => "logstash-%{+YYYY.MM.dd}"
        manage_template => false
        template_name => "template-web_access_log"
    }
}

上面配置中每个配置项含义如下:

  • host:是一个数组类型的值,后面跟的值是elasticsearch节点的地址与端口,默认端口是9200。可添加多个地址。
  • index:写入elasticsearch的索引的名称,这里可以使用变量。Logstash提供了%{+YYYY.MM.dd}这种写法。在语法解析的时候,看到以+ 号开头的,就会自动认为后面是时间格式,尝试用时间格式来解析后续字符串。这种以天为单位分割的写法,可以很容易的删除老的数据或者搜索指定时间范围内的数据。此外,注意索引名中不能有大写字母。
  • manage_template:用来设置是否开启logstash自动管理模板功能,如果设置为false将关闭自动管理模板功能。如果我们自定义了模板,那么应该设置为false。
  • template_name:这个配置项用来设置在Elasticsearch中模板的名称。

输出到elasticsearch示例

下面测试对系统日志/var/log/syslog/var/log/auth.log 进行收集,配置logstash如下的配置文件:
vim /home/rx/soft/elastic/logstash-7.1.0/config/output_config/logstash-to-es.conf 写入内容:

input {
    file {
        path => ["/var/log/syslog"]
        type => "system"
        tags => ["syslog","test"]
        start_position => "beginning"
    }
    file {
        path => ["/var/log/auth.log"]
        type => "system"
        tags => ["auth","test"]
        start_position => "beginning"
    }
}
filter {
}
output {
    if [type] == "system" {
        if [tags][0] == "syslog" {
            elasticsearch {
                hosts  => ["http://192.168.0.211:9200","http://192.168.0.212:9200","http://192.168.0.213:9200"]
                index  => "logstash-system-syslog-%{+YYYY.MM.dd}"
            }
            stdout { codec=> rubydebug }
        }
        else if [tags][0] == "auth" {
            elasticsearch {
                hosts  => ["http://192.168.0.211:9200","http://192.168.0.212:9200","http://192.168.0.213:9200"]
                index  => "logstash-system-auth-%{+YYYY.MM.dd}"
            }
            stdout { codec=> rubydebug }
        }
    }
}
  • 以上配置的hosts部分使用了集群配置,如果是单个ES服务,直接使用单个IP和端口即可,例如:hosts => [“http://127.0.0.1:9200”]
  • start_position => “beginning” 表示从文件头部开始收集

启动 logstash:./logstash-7.1.0/bin/logstash -r -f ./logstash-7.1.0/config/output_config/logstash-to-es.conf
启动后就开始收集日志了:
在这里插入图片描述

启动kibana

修改 kibana/config/kibana.yml 里面关于ES的内容:

elasticsearch.hosts: ["http://localhost:9200"]

然后启动ES 和 kibana:

./elasticsearch-7.1.0/bin/elasticsearch #启动ES
./kibana-7.1.0-linux-x86_64/bin/kibana #启动kibana

浏览器访问 http://localhost:5601/ 打开kibana的页面,进入 Management > Index management 即可看到最新收集到的日志索引:
在这里插入图片描述

在kibana中配置索引数据

进入 kibana 管理页面的 Management > Index Patterns > Create index pattern:
在这里插入图片描述
下一步:
在这里插入图片描述
创建完成:
在这里插入图片描述
然后在 Discover 中就可以看到最新收集的日志了:
在这里插入图片描述

补充内容:Logstash的条件判断语法

比较操作符

相等: ==, !=, <, >, <=, >=
正则: =~(匹配正则), !~(不匹配正则)
包含: in(包含), not in(不包含)

布尔操作符

and(与), or(或), nand(非与), xor(非或)

一元运算符:

!(取反)
()(复合表达式), !()(对复合表达式结果取反)
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Logstash是一个用于数据采集、处理和传输的开源工具。要创建Logstash集群,需要安装Logstash配置多个实例来运行。以下是一种可能的方法: 1. 首先,确保已在每个节点上安装Logstash。按照引用的指示,在每个节点的Logstash安装目录下使用命令"./bin/logstash -f logstash.conf"来运行Logstash。 2. 接下来,您可以使用引用的命令"/usr/share/logstash/bin/logstash-plugin list"来查看已安装的Logstash插件。 3. 要配置Logstash集群,您需要在每个节点的Logstash配置文件进行相应的更改。根据引用的示例,您可以将配置文件放在/etc/logstash目录下,并使用符号链接将其链接到Logstash的安装目录。 4. 在每个节点的配置文件,您可以定义输入、过滤器和输出。根据您的需求,可以使用不同的输入插件来收集数据,使用过滤器插件对数据进行处理和转换,并使用输出插件将数据发送到目标位置。 5. 在每个节点上启动Logstash实例,使用引用的命令"./bin/logstash -f logstash.conf"。这样,每个节点都将开始处理和传输数据。 通过以上步骤,您可以创建一个Logstash集群,用于处理和传输数据。请注意,这只是一种实现集群的方法,您可以根据具体需求进行调整和配置。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Logstash:如何连接到带有 HTTPS 访问的集群](https://blog.csdn.net/UbuntuTouch/article/details/126868040)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Logstash完成ELK集群](https://blog.csdn.net/kali_yao/article/details/120194822)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浮尘笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值