荐 OS性能分析命令(三)常用性能分析命令
文章目录
一、sar
1.1 命令说明
sysstat是Linux 系统中的常用工具包,而sar 是 Linux中sysstat工具包中的用于监控Linux系统性能的工具之一。
sysstat 工具包中包含两种类型的工具:即时查看工具(iostat、mpstat、sar);累计统计工具(sar);
sar命令又叫做系统活动情况报告。不仅可以实时查看服务器的性能,还可以做累计统计。sar命令的监控范围如下:
- 文件的读写情况
- 系统调用的使用情况
- 磁盘I/O使用情况
- CPU的使用统计
- 内存使用状况
- 进程活动
- IPC有关的活动
sar命令使用格式:
sar + 命令行选项(可选) + 间隔时间(可选) + 次数(可选)
常用来判断一个系统瓶颈问题
查询CPU
可用 sar -u 和 sar -q 等来查看
查询内存
可用 sar -B、sar -r 和 sar -W 等来查看
查询io
可用 sar -b、sar -u 和 sar -d 等来查看
系统会通过调用 /usr/lib64/sa/ 中的三个工具(sa1 sa2 sadc)来实现,周期地记录当时的系统性能的信息的功能。
sa1 :收集并将每天的系统性能的信息写入一个二进制的文件中,它是sadc的前端程序
sa2 :收集每天的系统活跃的信息并写入总结性的文件中,其作为 sar的前端程序
sadc :收集系统的动态数据的数据并写入一个二进制的文件中,其作为 sar 工具的后端
sar是由有类似日志切割的功能的,它会依据/etc/cron.d/sysstat中的计划任务,将日志放入/var/log/sa/中
注:日志为二进制文件,不可使用more、less、vim工具查看,必须使用sar或sadf
可以根据需求修改该计划任务
1.2 参数说明
sar [options] [-A] [-o file] t [n]
在命令行中,n 和t 两个参数组合起来定义采样间隔和次数,t为采样间隔,是必须有的参数,n为采样次数,是可选的,默认值是1,-o file表示将命令结果以二进制格式存放在文件中,file 在此处不是关键字,是文件名。options 为命令行选项。
-A 所有报告的总和
-B 输出内存页面的统计信息
-b 输出I/O和传送速率的统计信息
-C 输出进程统计信息及每秒创建的进程数
-d 输出每一个块设备的活动信息
-H 输出交换空间利用率信息
-h 输出帮助信息
-p 输出友好设备名字,以方便查看,常与-d和-n参数结合使用
-q 输出进程队列长度和系统平均负载状态统计信息
-R 输出内存页面的统计信息
-r 输出内存和交换空间的统计信息
-S 输出交换空间利用率信息
-t 读取 /var/log/sa/下的某日志的数据时显示其中记录的原始时间
-u 输出整体CPU使用情况的统计信息
-V 输出版本信息
-v 输出内核表状况统计信息(inode、文件和其他内核表的统计信息)
-W 输出系统交换的统计信息
-w 输出任务创建与系统转换统计信息
-y 输出终端设备的活动信息
-I 输出指定中断的统计信息,后方可加参数{...|SUM|ALL|XALL}
... 指定中断号
SUM 指定输出每秒接收到的中断总数
ALL 指定输出前16个中断
XALL 指定输出全部的中断信息
-P 输出指定的部分的CPU的统计信息,后方可加参数{cpu|ALL}
cpu 指定cpu
ALL 输出单个和整体cpu的统计数据
-n 输出网络设备(网卡)状态统计信息,后方可加参数{DEV|EDEV|NFS|NFSD|SOCK|ALL}
DEV 输出网络设备的统计信息
EDEV 输出网络设备的错误统计信息
NFS 输出NFS客户端的活动统计信息
NFSD 输出NFS服务器的活动统计信息
SOCK 输出网络套接字的使用统计信息
ALL 输出所有类型的网络活动统计信息
-f 从文件中读取数据信息。一般读取sar日志,也可读取-o选项生成的文件,后方要加文件名
-o 将sar的输出信息保存到文件中,后方要加文件名
-i 指定间隔时长,单位为秒
-s 指定输出统计数据的起始时间(格式为hh:mm:ss;例如01:00:00)
-e 指定输出统计数据的截至时间,通常与-S选项连用。无数值时默认为18:00:00(格式为hh:mm:ss;例如09:00:00)
1.3 结果说明
历史数据
sar命令会自动保存一个月的监控数据sar -f /var/log/sa/sa15
cpu
sar -u 3 1
%usr CPU在用户模式下,执行进程的时间百分比
%nice CPU在用户模式下,用于nice操作,所占用CPU总时间的百分比
%system CPU处在系统模式(内核态)下,执行进程的时间百分比
%iowait CPU用于等待I/O操作完成(等待输入输出完成),占用CPU总时间的百分比
%steal 管理程序为另一个虚拟进程提供服务而等待虚拟CPU的百分比
%idle CPU空闲时间百分比
注意:
如果%iowait的值过高,表示硬盘存在I/O瓶颈
如果%idle值高,表示CPU较空闲
如果%idle 的值高但系统响应慢时,有可能是 CPU 等待分配内存,此时应加大内存容量
如果%idle 的值持续低于10,则系统的 CPU 处理能力相对较低,表明系统中最需要解决的资源是 CPU
I/O
sar -b 3 1
tps 每秒向磁盘设备请求数据的次数,包括读、写请求,其为rtps与wtps的和。每一次IO下发后会先将多个请求合并为一个I/O磁盘请求,这里tps指请求合并后的请求计数
rtps 每秒向磁盘设备的读请求次数
wtps 每秒向磁盘设备的写请求次数
bread/s 每秒钟从物理设备读入的数据量,单位为 块/s
bwrtn/s 每秒钟向物理设备写入的数据量,单位为 块/s
设备使用情况
sar -d 3 1
DEV 磁盘设备,加上用参数-p可以打印出sda等磁盘设备名称;如不加参数-p,设备则显示为dev253-0等
tps 每秒向磁盘设备请求数据的次数,包括读、写请求,其为rtps与wtps的和。每一次IO下发后会先将多个请求合并为一个I/O磁盘请求,这里tps指请求合并后的请求计数
rd_sec/s 每秒读扇区的次数
wr_sec/s 每秒写扇区的次数
avgrq-sz 平均每次设备I/O操作的数据大小(扇区)
avgqu-sz 磁盘请求队列的平均长度
await 从请求磁盘到系统处理完,每次请求的平均消耗时间,包括请求队列等待时间(单位是毫秒)
svctm 系统处理每次请求的平均时间,不包括在请求队列中消耗的时间
%util I/O请求占CPU的百分比
网络设备统计信息
sar -n EDEV
IFACE 网络设备名
rxpck/s 每秒接收的包数量
txpck/s 每秒传输的包数量
rxbyt/s 每秒接收的字节数(单位为byte)
txbyt/s 每秒传输的字节数(单位为byte)
rxkB/s 每秒收的数据量(单位为kB)
txkB/s 每秒发的数据量(单位为kB)
rxcmp/s 每秒接收压缩包的数量
txcmp/s 每秒传输压缩包的数量
rxmcst/s 每秒接收的多播(multicast)包的总数排查网络设备故障
网络设备故障信息
sar -n EDEV |egrep ‘eth0|IFACE’
IFACE 网络设备名
rxerr/s 每秒接收的坏包数量
txerr/s 传输包时每秒发生错误的数量
coll/s 传输包时每秒发生冲突的数量
rxdrop/s 接收包时,每秒丢弃的包的数量(缺乏缓存导致)
txdrop/s 传输包时,每秒丢弃的包的数量(缺乏缓存导致)
txcarr/s 传输包时,每秒发生的传输错误的数量
rxfram/s 接收包时,每秒发生帧校验错误的数量
rxfifo/s 接收包时,每秒钟缓冲区溢出错误的数量
txfifo/s 传输包时,每秒钟缓冲区溢出错误的数量
内存分页状态
sar -B 3 1
pgpgin/s 每秒从磁盘空间或交换空间置换到内存的字节数(单位为KB)
pgpgout/s 每秒从内存置换到磁盘空间或交换空间的字节数(单位为KB)
fault/s 每秒钟系统产生的缺页数(主缺页加次缺页)
majflt/s 每秒钟产生的主缺页数
pgfree/s 每秒被放入空闲队列中的页个数
pgscank/s 每秒被kswapd扫描的页个数
pgscand/s 每秒直接被扫描的页个数
pgsteal/s 每秒钟从cache中被清除来满足内存需要的页个数
%vmeff 每秒清除的页占总扫描页的百分比
进程队列长度和平均负载状态
sar -q 3 1
runq-sz 运行队列的长度,等待运行的进程数量
plist-sz 进程列表中进程和线程的数量
ldavg-1 最后1分钟的系统平均负载
ldavg-5 过去5分钟的系统平均负载
ldavg-15 过去15分钟的系统平均负载
内存和交换空间状态
sar -r 3 1
kbmemfree 空闲的内存数量(单位为KB)
kbmemused 已使用的内存数量,不包含内核使用的内存(单位为KB)
%memused 已使用内存的百分数
kbbuffers 内核缓冲区buffer,使用的内存数量(单位为KB)
kbcached 内核高速缓存cache数据使用的内存数量(单位为KB)
kbcommit 保证当前系统所需要的内存,即为了确保不溢出而需要的内存(RAM+swap)
%commit kbcommit与所有内存总量的百分比
系统交换活动信息
sar -W 3 1
pswpin/s 每秒系统换入的交换页面数量
pswpout/s 每秒系统换出的交换页面数量
查看凌晨1点到3点的cpu
sar -s 01:00:00 -e 03:00:00
查看凌晨1点到3点的系统的平均负载
若要看某时间段其他性能,加上对应选项
默认监控: sar 5 5 // CPU和IOWAIT统计状态
(1) sar -b 5 5 // IO传送速率
(2) sar -B 5 5 // 页交换速率
(3) sar -c 5 5 // 进程创建的速率
(4) sar -d 5 5 // 块设备的活跃信息
(5) sar -n DEV 5 5 // 网路设备的状态信息
(6) sar -n SOCK 5 5 // SOCK的使用情况
(7) sar -n ALL 5 5 // 所有的网络状态信息
(8) sar -P ALL 5 5 // 每颗CPU的使用状态信息和IOWAIT统计状态
(9) sar -q 5 5 // 队列的长度(等待运行的进程数)和负载的状态
(10) sar -r 5 5 // 内存和swap空间使用情况
(11) sar -R 5 5 // 内存的统计信息(内存页的分配和释放、系统每秒作为BUFFER使用内存页、每秒被cache到的内存页)
(12) sar -u 5 5 // CPU的使用情况和IOWAIT信息(同默认监控)
(13) sar -v 5 5 // inode, file and other kernel tablesd的状态信息
(14) sar -w 5 5 // 每秒上下文交换的数目
(15) sar -W 5 5 // SWAP交换的统计信息(监控状态同iostat 的si so)
(16) sar -x 2906 5 5 // 显示指定进程(2906)的统计信息,信息包括:进程造成的错误、用户级和系统级用户CPU的占用情况、运行在哪颗CPU上
(17) sar -y 5 5 // TTY设备的活动状态
(18) 将输出到文件(-o)和读取记录信息(-f)
二、ps
2.1 命令说明
ps是Linux系统命令之一,是在Linux中是查看进程的命令。查看 Linux 中当前运行的进程的命令,包括进程号、命令、CPU使用量、内存使用量等。
2.2 参数说明
进程有5种状态
运行(正在运行或在运行队列中等待)
中断(休眠中, 受阻, 在等待某个条件的形成或接受到信号)
不可中断(收到信号不唤醒和不可运行, 进程必须等待直到有中断发生)
僵死(进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放)
停止(进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行)
进程的5种状态码
R 运行 runnable (on run queue)
S 中断 sleeping
D 不可中断 uninterruptible sleep (usually IO)
T 停止 traced or stopped
Z 僵死 a defunct (”zombie”) process
常用选项
-A 显示所有进程(等价于-e)(utility)
-a 显示一个终端的所有进程,除了会话引线
-N 忽略选择。
-d 显示所有进程,但省略所有的会话引线(utility)
-x 显示没有控制终端的进程,同时显示各个命令的具体路径。dx不可合用。(utility)
-p pid 进程使用cpu的时间
-u uid or username 选择有效的用户id或者是用户名
-g gid or groupname 显示组的所有进程。
U username 显示该用户下的所有进程,且显示各个命令的详细路径。如:ps U zhang;(utility)
-f 全部列出,通常和其他选项联用。如:ps -fa or ps -fx and so on.
-l 长格式(有F,wchan,C 等字段)
-j 作业格式
-o 用户自定义格式。
v 以虚拟存储器格式显示
s 以信号格式显示
-m 显示所有的线程
-H 显示进程的层次(和其它的命令合用,如:ps -Ha)(utility)
e 命令之后显示环境(如:ps -d e; ps -a e)(utility)
h 不显示第一行
2.3 结果说明
ps -aux
- USER 用户名
- PID 进程ID(Process ID)
- %CPU 进程的cpu占用率
- %MEM 进程的内存占用率
- VSZ 进程所使用的虚存的大小(Virtual Size)
- RSS 进程使用的驻留集大小或者是实际内存的大小,Kbytes字节。
- TTY 与进程关联的终端(tty)
- STAT 进程的状态:进程状态使用字符表示的(STAT的状态码)
- R 运行 Runnable (on run queue) 正在运行或在运行队列中等待。
- S 睡眠 Sleeping 休眠中, 受阻, 在等待某个条件的形成或接受到信号。
- I 空闲 Idle
- Z 僵死 Zombie(a defunct process) 进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放。
- D 不可中断 Uninterruptible sleep (ususally IO) 收到信号不唤醒和不可运行, 进程必须等待直到有中断发生。
- T 终止 Terminate 进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行。
- P 等待交换页
- W 无驻留页 has no resident pages 没有足够的记忆体分页可分配。
- X 死掉的进程
- < 高优先级进程 高优先序的进程
- N 低优先 级进程 低优先序的进程
- L 内存锁页 Lock 有记忆体分页分配并缩在记忆体内
- s 进程的领导者(在它之下有子进程);
- l 多进程的(使用 CLONE_THREAD, 类似 NPTL pthreads)
- + 位于后台的进程组
- START 进程启动时间和日期
- TIME 进程使用的总cpu时间
- COMMAND 正在执行的命令行命令
ps -elf
F: 代表这个程序的旗标 (flag), 4 代表使用者为 super user
S: 睡眠 Sleeping 休眠中, 受阻, 在等待某个条件的形成或接受到信号。
UID: 用户ID(User ID)
PID: 进程ID(Process ID)
PPID: 父进程的进程ID(Parent Process id)
C: CPU 使用的资源百分比
PRI: 这个是 Priority (优先执行序) 的缩写,详细后面介绍
NI: 这个是 Nice 值,在下一小节我们会持续介绍
ADDR: 这个是 kernel function,指出该程序在内存的那个部分。如果是个 running的程序,一般就是 “-”
SZ: 使用掉的内存大小
WCHAN: 目前这个程序是否正在运作当中,若为 - 表示正在运作
TTY: 登入者的终端机位置
TIME: 使用掉的 CPU 时间。
CMD 所下达的指令为何
三、 watch
3.1 命令说明
实时监测命令,还可以检测其他命令运行情况的命令
3.2 参数说明
- -d 高亮显示变动
- -n 周期(秒)
3.3 结果说明
每秒监测,高亮显示变化。
四、strace
4.1 命令说明
Strace命令用来跟踪进程执行时的系统调用和所接收的信号。在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁 盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通过系统调用访问硬件设备。strace可以跟踪到一个进程产生的系统调用,包括参 数,返回值,执行消耗的时间
4.2 参数说明
strace使用参数
- -p:跟踪指定的进程。
- -f:跟踪由fork子进程系统调用。
- -F:尝试跟踪vfork子进程系统调吸入,与-f同时出现时, vfork不被跟踪。
- -o filename:默认strace将结果输出到stdout。通过-o可以将输出写入到filename文件中。
- -ff:常与-o选项一起使用,不同进程(子进程)产生的系统调用输出到filename.PID文
- -r:打印每一个系统调用的相对时间。
- -t:在输出中的每一行前加上时间信息。 -tt 时间确定到微秒级。还可以使用-ttt打印相对时间。
- -v:输出所有系统调用。默认情况下,一些频繁调用的系统调用不会输出。
- -s:指定每一行输出字符串的长度,默认是32。文件名一直全部输出。
- -c:统计每种系统调用所执行的时间,调用次数,出错次数。
- -e expr:输出过滤器,通过表达式,可以过滤出掉你不想要输出。
- -d:输出strace关于标准错误的调试信息。
- -h:输出简要的帮助信息。
- -i:输出系统调用的入口指针。
- -q:禁止输出关于脱离的消息。
- -tt:在输出中的每一行前加上时间信息,微秒级。
- -T:显示每一调用所耗的时间。
- -V :输出strace的版本信息。
- -x:以十六进制形式输出非标准字符串。
- -xx:所有字符串以十六进制形式输出。
4.3 结果说明
strace -ff -F -o mysql.log mysql -uroot -p -h127.0.0.1 -P3307 跟踪MySQL命令的执行情况
当某个函数执行失败时,那么返回值一般为-1
五、lsof
5.1 命令说明
lsof的原始功能是列出打开的文件的进程。Linux下一切皆文件。
5.2 参数说明
- -a :列出打开文件存在的进程
- -c<进程名> :列出指定进程所打开的文件
- -g :列出GID号进程详情
- -d<文件号> :列出占用该文件号的进程
- +d<目录> :列出目录下被打开的文件
- +D<目录> :递归列出目录下被打开的文件
- -n<目录> :列出使用NFS的文件
- -i<条件> :列出符合条件的进程。
- -p<进程号>: 列出指定进程号所打开的文件
- -u 后面跟username:列出该用户相关进程所打开文件
- -U :仅列出系统socket文件类型
- -h:显示帮助信息
- -v:显示版本信息
5.3 结果说明
列出所有root用户下的socket文件进程
- COMMAND:进程的名称
- PID:进程标识符
- USER:进程所有者
- FD:文件描述符,应用程序通过文件描述符识别该文件。如cwd、txt等
- TYPE:文件类型,如DIR、REG等
- DEVICE:指定磁盘的名称
- SIZE:文件的大小
- NODE:索引节点(文件在磁盘上的标识)
- NAME:打开文件的确切名称
六、perf
6.1 命令说明
perf是内置于Linux内核源码树中的性能剖析(profiling)工具,它基于事件采样原理,以性能事件为基础,支持针对处理器相关性能指标与操作系统相关性能指标的性能剖析,常用于性能瓶颈的查找与热点代码的定位。
通过它,应用程序可以利用 PMU,tracepoint 和内核中的特殊计数器来进行性能统计。它不但可以分析指定应用程序的性能问题 (per thread),也可以用来分析内核的性能问题,当然也可以同时分析应用代码和内核,从而全面理解应用程序中的性能瓶颈。
使用 perf,您可以分析程序运行期间发生的硬件事件,比如 instructions retired ,processor clock cycles 等;您也可以分析软件事件,比如 Page Fault 和进程切换。这使得 Perf 拥有了众多的性能分析能力,举例来说,使用 Perf 可以计算每个时钟周期内的指令数,称为 IPC,IPC 偏低表明代码没有很好地利用 CPU。Perf 还可以对程序进行函数级别的采样,从而了解程序的性能瓶颈究竟在哪里等等。Perf 还可以替代 strace,可以添加动态内核 probe 点,还可以做 benchmark 衡量调度器的好坏。
6.2 参数说明
annotate 解析perf record生成的perf.data文件,显示被注释的代码。
archive 根据数据文件记录的build-id,将所有被采样到的elf文件打包。利用此压缩包,可以再任何机器上分析数据文件中记录的采样数据。
bench perf中内置的benchmark,目前包括两套针对调度器和内存管理子系统的benchmark。
buildid-cache 管理perf的buildid缓存,每个elf文件都有一个独一无二的buildid。buildid被perf用来关联性能数据与elf文件。
buildid-list 列出数据文件中记录的所有buildid。
diff 对比两个数据文件的差异。能够给出每个符号(函数)在热点分析上的具体差异。
evlist 列出数据文件perf.data中所有性能事件。
inject 该工具读取perf record工具记录的事件流,并将其定向到标准输出。在被分析代码中的任何一点,都可以向事件流中注入其它事件。
kmem 针对内核内存(slab)子系统进行追踪测量的工具
kvm 用来追踪测试运行在KVM虚拟机上的Guest OS。
list 列出当前系统支持的所有性能事件。包括硬件性能事件、软件性能事件以及检查点。
lock 分析内核中的锁信息,包括锁的争用情况,等待延迟等。
mem 内存存取情况
record 收集采样信息,并将其记录在数据文件中。随后可通过其它工具对数据文件进行分析。
report 读取perf record创建的数据文件,并给出热点分析结果。
sched 针对调度器子系统的分析工具。
script 执行perl或python写的功能扩展脚本、生成脚本框架、读取数据文件中的数据信息等。
stat 执行某个命令,收集特定进程的性能概况,包括CPI、Cache丢失率等。
test perf对当前软硬件平台进行健全性测试,可用此工具测试当前的软硬件平台是否能支持perf的所有功能。
timechart 针对测试期间系统行为进行可视化的工具
top 类似于linux的top命令,对系统性能进行实时分析。
trace 关于syscall的工具。
probe 用于定义动态检查点。
6.3 结果说明
perf list
查看当前软硬件环境、支持的性能事件。
- 硬件性能事件
- 软件性能事件
- tracepoint event
hw和cache是由 PMU 硬件产生的事件,比如 cache 命中,当您需要了解程序对硬件特性的使用情况时,便需要对这些事件进行采样
sw 是内核软件产生的事件,比如进程切换,tick 数等,与硬件无关
tracepoint是内核中的静态 tracepoint 所触发的事件,这些 tracepoint 用来判断程序运行期间内核的行为细节,比如 slab 分配器的分配次数等。
#事件分类
perf list | awk -F: '/Tracepoint event/ { lib[$1]++ } END { for (l in lib) { printf " %-16s %d\n", l, lib[l] } }' | sort | column
perf top
实时显示系统/进程的性能统信息
perf top -a -p 31317 # 分析整个 31317 进程的性能
perf top -n -p 31317 # 显示事件数量
perf top --show-total-period -p 31317 # 累计事件个数
注意,如果该命令黑屏需要升级perf命令至相应版本
第一列: 性能事件在整个检测域中占的比例,符号的 热度
第二列: 符号所在 DSO(Dynamic Shared Object)
第三列: DSO 类型(ELF可执行文件,动态链接库,内核,内核模块,VDSO 等)
第四列: 符号名(函数名)
pert stat
分析程序的整体性能
perf stat -e task-clock ./a.out # 分析 task-clock 事件
perf stat -p 31317 # 分析 31317 进程
perf stat -t 31318 # 分析 31318 线程
perf stat -r 5 ./a.out # 分析 5 次就停止
perf stat -d ./a.out # 全面分析
perf record/report
perf record: 记录一段时间内系统/进程的性能事件,生成 perf.data 文件
perf report: 读取 perf.data 文件,并显示分析数据
perf record -g -p 31655 # 记录一段时间的 zone_server 性能事件
perf report -i perf.data # 得到分析结果
perf report -n # 显示对应时间的调用次数
perf report -v # 显示每个符号的地址
perf report -g flat,5% #
perf report -g graph,5% #
perf report -g fractal,5% #
perf timechart
将系统的运行状态以 SVG 图的形式输出。
各处理器状态(run, idle)
各进程的时间图谱(run, sleep, blocked …)
perf timechart record
perf timechart
perf script
查看 perf 数据文件 (perf.data)
perf script -l # 查看当前系统中可扩展脚本
perf script syscall-count # 查看系统调用被调度次数
perf script sctop # 实时查看各个系统调用被调用的次数
perf火焰图
1、第一步
perf record -e cpu-clock -g -p 28591
Ctrl+c结束执行后,在当前目录下会生成采样数据perf.data.
2、第二步
用perf script工具对perf.data进行解析
perf script -i perf.data &> perf.unfold
3、第三步
将perf.unfold中的符号进行折叠:
./stackcollapse-perf.pl perf.unfold &> perf.folded
4、最后生成svg图:
./flamegraph.pl perf.folded > perf.svg
本文地址:https://blog.csdn.net/qq_42979842/article/details/107230148
下一篇: 京东天猫杀招对垒,谁能制霸双十一高地?