Java服务化系统线上应急和技术攻关,你必须掌握的Linux命令

Java服务化系统线上应急和技术攻关,你必须掌握的Linux命令


上一篇文章《Java服务化系统线上应急和技术攻关,你必须拥有的那些应用层脚本和Java虚拟机命令》介绍了笔者在互联网公司里线上应急和技术攻关过程中积累的应用层脚本和Java虚拟机命令,这些脚本和命令在发现问题和定位问题的过程中起到关键作用,然而,经常会遇到一些深层次的问题,仅仅通过应用层和JVM虚拟机层的信息无法定位问题和解决问题,这时需要深入研究系统级的各种参数和信息,才能确定问题的根源原因,例如:网络超时、机器负载过高、JVM OOM、JVM和内核Bug等,这篇文章介绍那些重要的Linux基础和监控相关的命令。

本文并不是介绍Linux命令的手册,而是侧重于命令在特定场景下如何帮助应急人员和攻关人员定位问题并解决问题,因此,对于每个命令的介绍将直切主题,直接介绍命令使用的具体场景,而不是介绍命令的详细使用格式。

1 必不可少的基础命令和工具

1.1 grep

grep是Linux下通用的文本内容查找命令。

也可以利用它打印匹配的上下几行,线上查找问题的时候,可以使用下列命令,查找关键字,显示关键字出现行的后5行,并且给关键字着色。

使用方式:


  1. grep -5 'parttern' INPUT_FILE #打印匹配行的前后5行  
  2. grep -C 5 'parttern' INPUT_FILE #打印匹配行的前后5行  
  3. grep -A 5 'parttern' INPUT_FILE #打印匹配行的后5行  
  4. $grep -B 5 'parttern' INPUT_FILE #打印匹配行的前5行  
  5. grep -A -15  --color 1010061938 * #查找后着色 

1.2 find

通过文件名称查找文件的存在位置,名称查找支持模糊匹配。

使用方式:


  1. find . -name FILE_NAME 

命令输出:


  1. robert@robert-ubuntu1410:~$ find . -name VestaServer.java 
  2. ./working/workspace/vesta-id-generator/vesta-server/src/main/java/com/robert/vesta/server/VestaServer.java 

1.3 uptime

查看机器的启动时间、登录用户、平均负载等情况,通常用在线上应急或者技术攻关的时候来确定操作系统的重启时间。

使用方式:


  1. uptime 

命令输出:


  1. robert@robert-ubuntu1410:~$ uptime 
  2.  14:42:30 up  2:51,  3 users,  load average:0.03, 0.06, 0.06 

从上面输出可以看到如下信息:

  1. 当前时间:14:42:30
  2. 系统已运行的时间:2小时51分
  3. 当前在线用户:3个用户
  4. 系统平均负载:0.03, 0.06, 0.06,最近1分钟、5分钟、15分钟系统的负载情况

系统平均负载指在特定时间间隔内队列中运行的平均进程数。如果一个进程满足以下条件,它其就会位于运行队列中:

  1. 它没有在等待IO操作的结果
  2. 它没有主动进入等待状态(也就是没有调用'wait'相关的系统API)
  3. 没有被停止(例如:等待终止)

一般来说,每个CPU内核对应活动进程数不大于3,则系统运行良好,换句话说,也就是活动进程数小于CPU核数的3倍。

举例说明,如果你的服务器的cpu有3个核心,那么只要uptime最后输出的一串字符数值小于9,即表示系统负载正常。但是,如果系统负载超过10,那就表示当前系统负载过重,需要定位系统执行任务负载超标的原因。

1.4 lsof

列出系统当前打开的文件句柄,在Linux文件系统中,任何资源都是以文件句柄的形式管理的,例如:硬件设备、文件、网络套接字等,系统内部为每一种资源分配一个句柄,应用程序只能用操作系统分配的句柄来引用资源,因此,文件句柄为应用程序与基础操作系统之间的交互提供了通用的操作接口。

应用程序打开文件的描述符列表包含了大量的关于应用程序本身的运行信息,因此通过lsof工具查看这个文件句柄列表,对系统监控以及应急排错提供重要的帮助。

查看某一个进程打开的文件句柄:


  1. lsof -p 2862 

命令输出:


  1. robert@robert-ubuntu1410:~$ lsof -p 2862 | less 
  2. COMMAND  PID   USER   FD   TYPE             DEVICE SIZE/OFF    NODE NAME 
  3. java    2862 robert  cwd    DIR                8,1     4096  537041 /home/robert/working/workspace/vesta-id-generator/releases/vesta-id-generator-0.0.1-release/bin/vesta-rest-0.0.1 
  4. java    2862 robert  rtd    DIR                8,1     4096       2 / 
  5. java    2862 robert  txt    REG                8,1     5730 1064639 /home/robert/working/softwares/jdk1.8.0_20/bin/java 
  6. java    2862 robert  mem    REG                8,1  7216688 1318996 /usr/lib/locale/locale-archive 
  7. java    2862 robert  mem    REG                8,1 65525265 1189622 /home/robert/working/softwares/jdk1.8.0_20/jre/lib/rt.jar 
  8. java    2862 robert  mem    REG                8,1    80460 1189581 /home/robert/working/softwares/jdk1.8.0_20/jre/lib/i386/libnio.so 
  9. java    2862 robert  mem    REG                8,1   103299 1189580 /home/robert/working/softwares/jdk1.8.0_20/jre/lib/i386/libnet.so 
  10. java    2862 robert  mem    REG                8,1    81884 1583248 /usr/share/locale-langpack/zh_CN/LC_MESSAGES/libc.mo 
  11. java    2862 robert  mem    REG                8,1  3131363 1189479 /home/robert/working/softwares/jdk1.8.0_20/jre/lib/charsets.jar 
  12. java    2862 robert  mem    REG                8,1  3500527 1189621 /home/robert/working/softwares/jdk1.8.0_20/jre/lib/resources.jar 
  13. java    2862 robert  mem    REG                8,1  1179307 1330505 /home/robert/working/softwares/jdk1.8.0_20/jre/lib/ext/localedata.jar 
  14. java    2862 robert  mem    REG                8,1   615948 1189601 /home/robert/working/softwares/jdk1.8.0_20/jre/lib/jsse.jar 
  15. java    2862 robert  mem    REG                8,1  3860522 1330502 /home/robert/working/softwares/jdk1.8.0_20/jre/lib/ext/cldrdata.jar 
  16. java    2862 robert  mem    REG                8,1  1065895 1330501 /home/robert/working/softwares/jdk1.8.0_20/jre/lib/ext/bcprov-jdk15-132.jar 
  17. ...... 

查看某一个端口的使用方式:


  1. lsof -i :8080 

命令输出:


  1. robert@robert-ubuntu1410:~$ lsof -i :8080 
  2. COMMAND  PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME 
  3. java    2862 robert   19u  IPv6  21370      0t0  TCP *:http-alt (LISTEN) 

1.5 ulimit

Linux系统对每个登录用户,都限制其最大进程数和打开的最大文件句柄数。为提高性能,可以根据硬件资源的具体情况,设置各个用户的最大进程数和打开的最大文件句柄数。

可以用ulimit -a来显示当前的各种系统对用户使用资源的限制:


  1. robert@robert-ubuntu1410:~$ ulimit -a 
  2. core file size          (blocks, -c) 0 
  3. data seg size           (kbytes, -d) unlimited 
  4. scheduling priority             (-e) 0 
  5. file size               (blocks, -f) unlimited 
  6. pending signals                 (-i) 7921 
  7. max locked memory       (kbytes, -l) 64 
  8. max memory size         (kbytes, -m) unlimited 
  9. open files                      (-n) 1024 
  10. pipe size            (512 bytes, -p) 8 
  11. POSIX message queues     (bytes, -q) 819200 
  12. real-time priority              (-r) 0 
  13. stack size              (kbytes, -s) 8192 
  14. cpu time               (seconds, -t) unlimited 
  15. max user processes              (-u) 7921 
  16. virtual memory          (kbytes, -v) unlimited 
  17. file locks                      (-x) unlimited 

设置用户的最大进程数:


  1. ulimit -u 10240 

设置用户可以打开的最大文件句柄数:


  1. ulimit -n xx 

1.6 curl

程序开发后,会使用junit, testng以及jmock, mockito进行单元测试,单元测试后需要进行集成测试,由于当前的线上服务较多使用restful风格,那么集成测试的时候就需要进行HTTP调用,查看返回的结果是否符合预期,curl命令当然是首选测试的方法。

使用方式:


  1. curl -i  “http://www.sina.com” #打印请求响应头信息 
  2.  
  3. curl -v  “http://www.sina.com” #使用post方法 
  4. curl -verbose  “http://www.sina.com” #使用post方法 
  5.  
  6. curl -d ‘abc=def’ “http://www.sina.com” #使用head方法 
  7.  
  8. curl -I "http://www.sina.com" #打印HTTP响应码 
  9.  
  10. curl -sw '%{http_code}'  "http://www.sina.com" #打印HTTP响应码 

1.7 scp

scp命令是Linux系统中功能强大的文件传输命令,可以实现从本地到远程以及远程到本地的双向文件传输,用起来非常的方便。常用来在线上定位问题时,将线上的一些文件下载到本地进行详查,或者将本地的修改上传到服务器上。

使用方式:


  1. scp robert@192.168.1.1:/home/robert/test.txt .  
  2. scp ./test.txt robert@192.168.1.1:/home/robert/ 

1.8 vi & vim

vi和vim是Linux中最常用的命令行文本编辑工具,vim是vi的升级版本,在某些Linux版本下,vi实际上通过软连接指向vim。

笔者常用的vi/vim命令如下:

  1. h:左移一个字符
  2. l:右移一个字符,这个命令很少用,一般用w代替
  3. k:上移一个字符
  4. j:下移一个字符
  5. set number:显示行号
  6. shift + g:移动到最后一行
  7. 1 + shift + g:移动到第一行
  8. n + shift + g:移动到第n行
  9. 0: 移动到行首
  10. $:移动到行尾
  11. /text:查找text,按n健查找下一个,按N健查找前一个
  12. ?text:查找text,反向查找,按n健查找下一个,按N健查找前一个
  13. i:在当前位置生前插入
  14. I:在当前行首插入
  15. a:在当前位置后插入
  16. A:在当前行尾插入
  17. o:在当前行之后插入一行
  18. O:在当前行之前插入一行
  19. %s/old/new/g:用old替换new,替换当前行的所有匹配
  20. ctrl + f:向下滚动一屏
  21. ctrl + b:向上滚动一屏
  22. u:撤销
  23. U:撤销对整行的操作
  24. Ctrl + r:重做,即撤销的撤销
  25. x:删除当前字符
  26. dd:删除当前行
  27. 10d:删除当前行开始的10行
  28. yy:拷贝当前行
  29. p:在当前光标后粘贴,如果之前使用了yy命令来复制一行,那么就在当前行的下一行粘贴
  30. :wq:保存并退出
  31. :q!:强制退出并忽略所有更改

有了这些命令,基本可以在Linux系统命令行下做开发了,无论是开发脚本,还是线上应急或者技术攻关过程中在Linux系统中做编辑,都没有问题,建议大家把上面这个命令列表打印出来,贴在办公桌上,需要的时候可以看一眼,久而久之就记住了。

1.9 dos2unix & unix2dos

用于转换windows和unix的换行符,通常在windows上开发的脚本和配置,上传到unix上都需要转换。

使用方式:


  1. robert@robert-ubuntu1410:~$ dos2unix test.txt  
  2. dos2unix:converting file test.txt to Unix format ... 
  3.  
  4. robert@robert-ubuntu1410:~$ unix2dos test.txt  
  5. unix2dos:converting file test.txt to DOS format ... 

2 查看活动进程的命令

2.1 ps

显示系统内所有的进程。

使用方式:


  1. ps -elf 

输出:


  1. robert@robert-ubuntu1410:~$ ps -elf 
  2. F S UID        PID  PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD 
  3. 4 S root         1     0  0  80   0 -  8477 poll_s 09:56 ?        00:00:01 /sbin/init 
  4. 1 S root         2     0  0  80   0 -     0 kthrea 09:56 ?        00:00:00 [kthreadd] 
  5. 1 S root         3     2  0  80   0 -     0 smpboo 09:56 ?        00:00:00 [ksoftirqd/0] 
  6. 1 S root         4     2  0  80   0 -     0 worker 09:56 ?        00:00:00 [kworker/0:0] 
  7. 1 S root         5     2  0  60 -20 -     0 worker 09:56 ?        00:00:00 [kworker/0:0H] 
  8. 1 S root         7     2  0  80   0 -     0 rcu_gp 09:56 ?        00:00:00 [rcu_sched] 
  9. 1 S root         8     2  0  80   0 -     0 rcu_no 09:56 ?        00:00:00 [rcuos/0] 
  10. 1 R root         9     2  0  80   0 -     0 ?      09:56 ?        00:00:00 [rcuos/1] 
  11. 1 S root        10     2  0  80   0 -     0 rcu_no 09:56 ?        00:00:00 [rcuos/2] 
  12. 1 S root        11     2  0  80   0 -     0 rcu_no 09:56 ?        00:00:00 [rcuos/3] 
  13. 1 S root        12     2  0  80   0 -     0 rcu_gp 09:56 ?        00:00:00 [rcu_bh] 
  14. 1 S root        13     2  0  80   0 -     0 rcu_no 09:56 ?        00:00:00 [rcuob/0] 
  15. 1 S root        14     2  0  80   0 -     0 rcu_no 09:56 ?        00:00:00 [rcuob/1] 
  16. 1 S root        15     2  0  80   0 -     0 rcu_no 09:56 ?        00:00:00 [rcuob/2] 
  17. 1 S root        16     2  0  80   0 -     0 rcu_no 09:56 ?        00:00:00 [rcuob/3] 
  18. ...... 

根据进程的名字或者其他信息,通过grep命令找到目标进程,也可以打印进程启动脚本的全路径。

2.2 top

查看活动进程的CPU和内存信息的工具命令,能够实时显示系统中各个进程的资源占用情况。可以按CPU和内存的使用情况和执行时间对进程进行排序。

使用方式:


  1. top 

命令输出:


  1. top - 10:18:49 up 22 min,  2 users,  load average:0.10, 0.31, 0.22 
  2.    Tasks:195 total,   2 running, 193 sleeping,   0 stopped,   0 zombie 
  3.    %Cpu(s): 1.8 us,  0.2 sy,  0.0 ni, 98.0 id,  0.1 wa,  0.0 hi,  0.0 si,  0.0 st 
  4.    KiB Mem:  2049416 total,  1636620 used,   412796 free,   117652 buffers 
  5.    KiB Swap: 2095100 total,     1480 used,  2093620 free.   643848 cached Mem 
  6.  
  7.      PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                            
  8.     1608 root      20   0  475836  74616  30232 S   4.0  3.6   0:12.21 Xorg                                                               
  9.     2363 robert    20   0 1380660 103000  63884 S   2.7  5.0   0:12.15 compiz                                                             
  10.     2157 robert    20   0  589920  30748  24412 S   1.3  1.5   0:00.98 unity-panel-ser                                                    
  11.     2769 robert    20   0  597884  35820  28008 S   0.7  1.7   0:04.95 gnome-terminal                                                     
  12.     ... 

从输出中可以看到整体的cpu占用率、cpu负载的情况、进程占用CPU和内存等资源的情况。另外top命令的输出把cache放在了swap一行,这并不重要,实际上它和swap没有太大的关系。

我们可以用top命令的快捷键转换输出的显示信息:

  1. t:切换显示进程和 CPU 状态信息
  2. m:切换显示进程和 CPU 状态信息
  3. A:分类显示各种系统资源的消耗情况。可用于快速识别系统的性能要求极高的任务
  4. o:改变显示项目的顺序
  5. r:重新设置进程的优先级别(系统提示用户输入需要改变的进程PID以及需要设置
  6. 的优先级值)
  7. k:终止一个进程(系统将提示用户输入需要终止的进程PID)
  8. s:改变刷新的时间间隔
  9. u:查看指定用户的进程

3 窥探内存的命令

3.1 free

此命令显示系统内存的使用情况,包括总体内存、已经使用的内存、以及系统核心使用的缓冲区,包括缓存(buffer)和缓冲(cache)等。

使用方式:


  1. free 

命令输出:


  1. robert@robert-ubuntu1410:~$ free 
  2.              total       used       free     shared    buffers     cached 
  3. Mem:      2049416    1646480     402936      13280     118596     646288 
  4. -/+ buffers/cache:    881596    1167820 
  5. Swap:     2095100       1480    2093620 

内存使用并不只有简单的占用和空闲两个状态,从上面的输出发现里面有buffer和cache的数据,从字面意义上来讲,都是缓存,那么弄清楚缓存什么数据才能有效的区分这两种缓存。

从上面命令的输出,我们可以看到,Buffer 118M, Cache 646M。其实,这两个内存区域都是用来缓存磁盘数据的,只不过缓存的数据是不同的:

  1. buffers一般都不太大,在一个通用的Linux系统中,一般都是在几十到几百M字节,用于存储磁盘块设备的元数据,比如哪些块属于哪些文件,文件的权限,目录等信息。
  2. cached一般会很大, 一般都是G字节以上, 用于存储读写文件的页, 当对一个文件进行读的时候, 会取磁盘文件页到此内存区域,然后从内存进行读取,当写入一个文件,会先写到此缓存,并将相关的页面标记为”dirty”。

buffers用于存储元数据,一般占用的空间不大,对它的关注也不多,cached一般会很大,随着读写磁盘的多少而自动的增加而减少,这也取决于物理内存是否够用,如果应用使用物理内存较多,操作系统会适当的缩小cached来保证用户进程对内存的需要。

3.2 pmap

此命令用来报告进程占用内存的详细情况,可以用来查出某些内存瓶颈问题的根源原因。

使用方式:


  1. pmap -d 2862 

命令输出:


  1. robert@robert-ubuntu1410:~$ pmap -d 2862 
  2. 2862:  java -server -Xms512m -Xmx512m -Xmn128m -XX:PermSize=128m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=60 -verbose:gc -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -Xloggc:./logs/gc.log -cp /home/robert/working/workspace/vesta-id-generator/releases/vesta-id-generator-0.0.1-release/bin/vesta-rest-0.0.1/extlib -jar ./lib/vesta-rest-0.0. 
  3. Address           Kbytes Mode  Offset           Device    Mapping 
  4. 0000000008048000       4 r-x-- 0000000000000000 008:00001 java 
  5. 0000000008049000       4 rw--- 0000000000000000 008:00001 java 
  6. 000000000a017000     872 rw--- 0000000000000000 000:00000   [ anon ] 
  7. 00000000be800000     896 rw--- 0000000000000000 000:00000   [ anon ] 
  8. 00000000be8e0000     128 ----- 0000000000000000 000:00000   [ anon ] 
  9. 00000000be900000    1920 rw--- 0000000000000000 000:00000   [ anon ] 
  10. 00000000beae0000     128 ----- 0000000000000000 000:00000   [ anon ] 
  11. 00000000beb00000     284 rw--- 0000000000000000 000:00000   [ anon ] 
  12. ...... 

这个命令显示比较底层的进程模块占用内存的信息,并且可以打印内存的起止地址等,用于定位深层次JVM或者操作系统的内存问题。

4 CPU使用情况监控命令

4.1 vmstat

此命令显示关于内核线程、虚拟内存、磁盘IO、陷阱和CPU占用率的统计信息。

使用方式:


  1. vmstat 

命令输出:


  1. robert@robert-ubuntu1410:~$ vmstat 
  2. procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- 
  3.  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st 
  4.  2  0   1480 404300 118252 646216    0    0    78    31   63  145  2  0 97  1  0 

这里面需要注意的是:

  1. buff是IO系统用来做存储磁盘块文件元数据的信息
  2. cache是操作系统用来缓存磁盘数据的缓冲区,操作系统会自动调节这个参数,在内存紧张的时候操作系统会减少cache的占用空间来保证其他进程可用
  3. cs参数表达线程切换次数,此数据太大表明线程同步机制有问题
  4. si和so如果较大说明系统频繁使用交换区,应该查看操作系统内存是否够用
  5. bi和bo代表IO活动,根据大小可以知道磁盘的负载

4.2 mpstat

实时监控系统CPU的一些统计信息,这些信息存放在/proc/stat文件中,在多核CPU系统里,其不但能查看所有CPU的平均使用信息,而且能够查看某一个特定CPU的信息。

使用方式:


  1. mpstat -P ALL 

命令输出:


  1. robert@robert-ubuntu1410:~$ mpstat -P ALL 
  2. Linux 3.16.0-30-generic (robert-ubuntu1410)     2017年04月23日     _x86_64_    (4 CPU) 
  3.  
  4. 11时12分38秒  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle 
  5. 11时12分38秒  all    0.54    0.55    0.23    0.57    0.00    0.04    0.00    0.00    0.00   98.07 
  6. 11时12分38秒    0    0.75    1.41    0.35    1.06    0.00    0.11    0.00    0.00    0.00   96.32 
  7. 11时12分38秒    1    0.51    0.22    0.22    0.48    0.00    0.01    0.00    0.00    0.00   98.57 
  8. 11时12分38秒    2    0.52    0.58    0.18    0.29    0.00    0.02    0.00    0.00    0.00   98.41 
  9. 11时12分38秒    3    0.40    0.01    0.15    0.45    0.00    0.01    0.00    0.00    0.00   98.98 

我们可以看到每个CPU核心的占用率、IO等待、软中断、硬中断等。

5 磁盘IO监控命令

5.1 iostat

监视CPU占用率和平均负载值,以及IO读写速度等。

这个命令的输出的每个字段都非常有用,r/s和w/s指的是IOPS,rkB/s和wkB/s指的是每秒的存取速度,await是平均等待时间,一般都在10ms左右。

另外,iotop、ioprofiler、blktrace可以监控更多底层的IO活动信息,本文就不展开介绍,vmstat、mpstat也有一些IO相关的信息输出。

使用方式:


  1. iostat -x 

命令输出:


  1. robert@robert-ubuntu1410:~$ iostat -x 
  2. Linux 3.16.0-30-generic (robert-ubuntu1410)     2017年04月23日     _x86_64_    (4 CPU) 
  3.  
  4. avg-cpu: %user   %nice %system %iowait  %steal   %idle 
  5.            0.61    0.68    0.31    0.70    0.00   97.72 
  6.  
  7. Device:        rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util 
  8. sda               2.69     3.43   11.92    1.56   217.23   118.91    49.87     0.21   15.45    9.39   61.69   2.18   2.94 

从命令输出可以看出:

  1. iowait较大说明IO负载大,IO等待比较严重,磁盘读写遇到瓶颈。
  2. 可以直接看到每秒读写速度的最大峰值。
  3. 也可以看到CPU的占用率情况。

5.2 swapon

查看交换分区的使用情况。

使用方式:


  1. /sbin/swapon -s 

命令输出:


  1. robert@robert-Latitude-E6440:~/tmp$ /sbin/swapon -s 
  2. Filename                Type        Size    Used    Priority 
  3. /dev/sda6              partition   4094972 708384   -1 

由输出可见交换分区共4G,已使用大约708M。

5.3 df

查看文件系统的硬盘挂载点和空间使用情况。

使用方式:


  1. df 

命令输出:


  1. robert@robert-Latitude-E6440:~/tmp$ df -h 
  2. 文件系统        容量  已用  可用 已用% 挂载点 
  3. /dev/sda5       220G   84G  125G   40% / 
  4. none            4.0K     0  4.0K    0% /sys/fs/cgroup 
  5. udev            2.0G  4.0K  2.0G    1% /dev 
  6. tmpfs           395M  1.3M  393M    1% /run 
  7. none            5.0M     0  5.0M    0% /run/lock 
  8. none            2.0G   52M  1.9G    3% /run/shm 
  9. none            100M   60K  100M    1% /run/user 

6 查看网络信息和网络监控命令

6.1 ifconfig

ifconfig可以查看机器挂载的网卡情况。

使用方式:


  1. ifconfig -a 

命令输出:


  1. robert@robert-ubuntu1410:~$ ifconfig -a 
  2. eth0      Link encap:以太网  硬件地址 08:00:27:2f:70:b6   
  3.           inet 地址:192.168.1.102  广播:192.168.1.255  掩码:255.255.255.0 
  4.           inet6 地址:fe80::a00:27ff:fe2f:70b6/64 Scope:Link 
  5.           UP BROADCAST RUNNING MULTICAST  MTU:1500  跃点数:1 
  6.           接收数据包:14392 错误:0 丢弃:0 过载:0 帧数:0 
  7.           发送数据包:8665 错误:0 丢弃:0 过载:0 载波:0 
  8.           碰撞:0 发送队列长度:1000  
  9.           接收字节:15021524 (15.0 MB)  发送字节:858553 (858.5 KB) 
  10.  
  11. lo        Link encap:本地环回   
  12.           inet 地址:127.0.0.1  掩码:255.0.0.0 
  13.           inet6 地址:::1/128 Scope:Host 
  14.           UP LOOPBACK RUNNING  MTU:65536  跃点数:1 
  15.           接收数据包:4161 错误:0 丢弃:0 过载:0 帧数:0 
  16.           发送数据包:4161 错误:0 丢弃:0 过载:0 载波:0 
  17.           碰撞:0 发送队列长度:0  
  18.           接收字节:331544 (331.5 KB)  发送字节:331544 (331.5 KB) 

可见机器有两个网卡,一个是eth0,一个是本地回环虚拟网卡。

6.2 ping

ping命令是检测网络故障常用的命令,可以用来测试一台主机到另外一台主机的网络是否联通。

使用方式:


  1. ping www.baidu.com 

命令输出:


  1. robert@robert-ubuntu1410:~$ ping www.baidu.com 
  2. PING www.a.shifen.com (111.13.100.92) 56(84) bytes of data. 
  3. 64 bytes from localhost (111.13.100.92):icmp_seq=1 ttl=54 time=4.91 ms 
  4. 64 bytes from localhost (111.13.100.92):icmp_seq=2 ttl=54 time=8.76 ms 
  5. ^C 
  6. --- www.a.shifen.com ping statistics --- 
  7. 2 packets transmitted, 2 received, 0% packet loss, time 1001ms 
  8. rtt min/avg/max/mdev = 4.917/6.838/8.760/1.923 ms 

6.3 telnet

telnet是TCP/IP协议族的一员,是网络远程登陆服务的标准协议,它为用户提供了在本地计算机上连接远程主机的能力和主要方式。

使用方式:


  1. telnet IP PORT 

命令输出:


  1. robert at robert in ~/working/softwares/redis-3.0.5/src  
  2. $ telnet localhost 6379 
  3. Trying ::1... 
  4. Connected to localhost. 
  5. Escape character is '^]'
  6. get hello 
  7. $3 
  8. world 

从上面输出可以看到,使用telnet协议可以直接连接redis端口,并发送redis命令。

6.4 nc

nc是NetCat的简称,在网络调试工具享有“瑞士军刀”的美誉,此命令功能丰富、短小精悍、简单实用,被设计成为一个易用的网络工具,可通过TCP/UDP协议传输数据。同时,它也是一个网络应用调试分析器,因为它可以根据需要创建各种不同类型的网络服务和连接,在调试Restful服务的时候,经常会发生不可预期的结果,这种情况下可以使用nc模拟启动服务器,把HTTP客户端连接到nc上,nc上会打印出Restful服务提供的所有参数,然后一一检查参数,找到问题。

当然,也可用于传输二进制或者文本文件。

传输文件端:


  1. robert@robert-ubuntu1410:~$ nc localhost 8888 < test.txt 

接受文件端:


  1. robert@robert-ubuntu1410:~$ nc -l 8888 
  2. 12345678 

6.5 mtr

Linux系统中的网络连通性测试工具,也可以用来检测丢包率。

使用方式:


  1. mtr -r sina.com 

命令输出:


  1. robert@robert-ubuntu1410:~$ mtr -r sina.com 
  2. Start:Sun Apr 23 16:40:27 2017 
  3. HOST:robert-ubuntu1410           Loss%   Snt   Last   Avg  Best  Wrst StDev 
  4.   1.|-- 192.168.1.1                0.0%    10    2.0   2.5   0.9  10.4   2.7 
  5.   2.|-- 172.30.44.1                0.0%    10    6.4   7.5   5.8  13.8   2.3 
  6.   3.|-- 10.1.10.201                0.0%    10    3.0   3.4   3.0   4.2   0.0 
  7.   4.|-- 111.63.14.97               0.0%    10    5.5   6.6   5.1  16.4   3.4 
  8.   5.|-- 111.11.74.9               90.0%    10   10.8  10.8  10.8  10.8   0.0 
  9.   6.|-- 111.11.65.117             90.0%    10    7.9   7.9   7.9   7.9   0.0 
  10.   7.|-- 221.183.26.205            80.0%    10    8.0   9.1   8.0  10.1   1.4 
  11.   8.|-- 221.176.16.250            80.0%    10   11.9  12.8  11.9  13.8   1.0 
  12.   9.|-- 221.176.21.194            90.0%    10   11.6  11.6  11.6  11.6   0.0 
  13.  10.|-- 202.97.15.177             90.0%    10   25.1  25.1  25.1  25.1   0.0 
  14.  11.|-- 202.97.88.237             90.0%    10   14.1  14.1  14.1  14.1   0.0 
  15.  12.|-- 202.97.53.110              0.0%    10   20.4  16.0  13.7  20.4   2.1 
  16.  13.|-- 202.97.58.114              0.0%    10   14.4  17.9  14.4  21.4   2.4 
  17.  14.|-- 202.97.51.86              40.0%    10  211.2 207.4 204.9 211.2   2.5 
  18.  15.|-- 203.14.186.34              0.0%    10  224.7 201.3 194.9 224.7  10.3 
  19.  16.|-- 218.30.41.234              0.0%     9  218.1 219.6 215.3 238.7   7.3 
  20.  17.|-- ???                       100.0     9    0.0   0.0   0.0   0.0   0.0 

其中第二列为丢包率,可以用来判断网络中两台机器连通性的质量。

6.6 nslookup

是一款检测网络中DNS服务器的是否能够正确解析域名的工具命令,并且可以输出。

使用方式:


  1. nslookup sina.com 

命令输出:


  1. robert@robert-ubuntu1410:~$ nslookup sina.com 
  2. Server:        127.0.1.1 
  3. Address:    127.0.1.1#53 
  4.  
  5. Non-authoritative answer: 
  6. Name:    sina.com 
  7. Address:66.102.251.33 

从输出可以看到,sina.com域名被正确解析到IP地址66.102.251.33。

6.7 traceroute

traceroute可以提供从你的主机到互联网另一端的主机走的什么路径,然而,每次数据包由某一同样的出发点到达某一同样的目的地走的路径可能会不一样,但通常来说大部分时候所走的路径是相同的。

使用方式:


  1. traceroute sina.com 

命令输出:


  1. robert@robert-ubuntu1410:~$ traceroute sina.com  
  2. traceroute to sina.com (66.102.251.33), 30 hops max, 60 byte packets 
  3.  1  192.168.1.1 (192.168.1.1)  4.373 ms  4.351 ms  4.337 ms 
  4.  2  172.30.44.1 (172.30.44.1)  9.573 ms  10.107 ms  10.422 ms 
  5.  3  10.1.1.2 (10.1.1.2)  4.696 ms  4.473 ms  4.637 ms 
  6.  4  111.63.14.97 (111.63.14.97)  6.118 ms  6.929 ms  6.904 ms 
  7.  5  * * * 
  8.  6  * * * 
  9.  7  * * * 
  10.  8  * * * 
  11.  9  * * * 
  12. 10  * * 221.176.23.54 (221.176.23.54)  22.312 ms 
  13. 11  * * * 
  14. 12  202.97.53.86 (202.97.53.86)  17.421 ms 202.97.53.34 (202.97.53.34)  29.006 ms 202.97.53.114 (202.97.53.114)  15.464 ms 
  15. 13  202.97.58.114 (202.97.58.114)  17.840 ms 202.97.58.122 (202.97.58.122)  16.655 ms  20.011 ms 
  16. 14  202.97.51.86 (202.97.51.86)  207.216 ms  207.157 ms  211.004 ms 
  17. 15  203.14.186.34 (203.14.186.34)  199.606 ms  196.477 ms  195.614 ms 
  18. 16  218.30.41.234 (218.30.41.234)  215.134 ms  214.705 ms  220.728 ms 
  19. 17  66.102.251.33 (66.102.251.33)  209.436 ms  210.263 ms  208.335 ms 

上面输出中记录按序列号从1开始,每个纪录就是网络一跳,每跳一次表示经过一个网关或者路由,我们看到每行有三个时间,单位是毫秒,指的是这一跳每次需要的时间。

6.8 sar

sar是一个多功能的监控工具,使用简单方便,不需要管理员权限,可以输出每秒的磁盘存取速度,适合线上排查问题时使用,命令小巧实用。

使用方式:


  1. sar -n DEV 1 1 

命令输出:


  1. robert@robert-ubuntu1410:~$ sar -n DEV 1 1 
  2. Linux 3.16.0-30-generic (robert-ubuntu1410)     2017年04月23日     _x86_64_    (4 CPU) 
  3.  
  4. 11时02分43秒     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil 
  5. 11时02分44秒      eth0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00 
  6. 11时02分44秒        lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00 
  7.  
  8. 平均时间:    IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil 
  9. 平均时间:     eth0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00 
  10. 平均时间:       lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00 

从上面的用法可以看到网卡的读写速度和流量,在现实的应急过程中,可以用来判断服务器是否上量。

此命令除了可以查看网卡的信息以外,sar可以用来收集更多的服务的状态信息:

  1. -A:所有报告的总和
  2. -u:CPU利用率
  3. -v:进程、I节点、文件和锁表状态
  4. -d:硬盘使用报告
  5. -r:没有使用的内存页面和硬盘块
  6. -g:串口 I/O的情况
  7. -b:缓冲区使用情况
  8. -a:文件读写情况
  9. -c:系统调用情况
  10. -R:进程的活动情况
  11. -y:终端设备活动情况
  12. -w:系统交换活动

6.9 netstat(ss)

此命令显示网络连接、端口信息等,另外一个命令ss与netstat命令类似,就不单独介绍。

6.9.1 根据进程查找端口

1.根据进程名字查找进程ID:


  1. ps -elf | grep 进程 

输出为:


  1. robert@robert-ubuntu1410:~$ ps -elf | grep vesta 
  2.  0 S robert    2862  1988 10  80   0 - 233215 futex_ 10:00 pts/0   00:00:22 java -server -Xms512m -Xmx512m -Xmn128m -XX:PermSize=128m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=60 -verbose:gc -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -Xloggc:./logs/gc.log -cp /home/robert/working/workspace/vesta-id-generator/releases/vesta-id-generator-0.0.1-release/bin/vesta-rest-0.0.1/extlib -jar ./lib/vesta-rest-0.0.1.jar 
  3.  0 R robert    2963  2778  0  80   0 -  3993 -      10:04 pts/0    00:00:00 grep --color=auto vesta 

获得进程ID为2862。

2.根据进程ID查找进程开启的端口:


  1. netstat -nap | grep 6588 

输出为:


  1. robert@robert-ubuntu1410:~$ netstat -nap | grep 2862 
  2.  tcp6       0      0 :::8080                 :::*                    LISTEN      2862/java        
  3.  unix  2      [ ]         流        已连接     21371    2862/java 

获得监听端口为8080。

6.9.2 根据端口查找进程

1.查找使用端口的进程号:


  1. netstat -nap | grep 8080 

输出为:


  1. robert@robert-ubuntu1410:~$ netstat -nap | grep 8080 
  2. cp6       0      0 :::8080                 :::*                    LISTEN      2862/java 

获得进程ID为2862。

2.根据进程ID查找进程的详细信息。


  1. ps -elf | grep 2862 

输出为:


  1. robert@robert-ubuntu1410:~$ ps -elf | grep 2862 
  2. 0 S robert    2862  1988  3  80   0 - 233215 futex_ 10:00 pts/0   00:00:23 java -server -Xms512m -Xmx512m -Xmn128m -XX:PermSize=128m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=60 -verbose:gc -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -Xloggc:./logs/gc.log -cp /home/robert/working/workspace/vesta-id-generator/releases/vesta-id-generator-0.0.1-release/bin/vesta-rest-0.0.1/extlib -jar ./lib/vesta-rest-0.0.1.jar 

6.10 iptraf

iptraf是一个实时查看网络流量的交互式的彩色的文本屏幕界面的监控工具。监控的数据比较全面,可输出TCP连接、网络接口、协议、端口、包大小等信息,但是耗费系统资源比较多,需要管理员权限。

使用方式:


  1. sudo iptraf 

命令输出:

在进入主界面之前可以选择不同的选项,在不同的选项下,可以查看不同维度的网络信息。

6.11 tcpdump

网络状况分析跟踪工具,可以用来抓包的一个实用的命令。要使用该工具,需要对TCP/IP协议有所熟悉,因为过滤使用的信息都来自TCP/IP协议的格式。

显示来源IP或者目的IP为192.168.1.102的网络通信:


  1. sudo tcpdump -i eth0 host 192.168.1.102 

显示去往102.168.1.102的所有ftp会话信息:


  1. tcpdump -i eth1 'dst 192.168.1.102 and (port 21 or 20)' 

显示去往102.168.1.102的所有HTTP会话信息:


  1. tcpdump -ni eth0 'dst 192.168.1.102 and tcp and port 8080' 

6.12 nmap

扫描某一主机打开的端口以及端口提供的服务信息,通常用于查看本机哪些端口对外提供服务,或者确定服务器哪些端口对外开放。

使用方式:


  1. nmap -v -A localhost 

命令输出:


  1. robert@robert-ubuntu1410:~$ nmap -v -A localhost 
  2.  
  3. Starting Nmap 6.40 ( http://nmap.org ) at 2017-04-23 12:11 CST 
  4. NSE:Loaded 110 scripts for scanning. 
  5. NSE:Script Pre-scanning. 
  6. Initiating Ping Scan at 12:11 
  7. Scanning localhost (127.0.0.1) [2 ports] 
  8. Completed Ping Scan at 12:11, 0.00s elapsed (1 total hosts) 
  9. Initiating Connect Scan at 12:11 
  10. Scanning localhost (127.0.0.1) [1000 ports] 
  11. Discovered open port 22/tcp on 127.0.0.1 
  12. Discovered open port 8080/tcp on 127.0.0.1 
  13. Discovered open port 25/tcp on 127.0.0.1 
  14. Discovered open port 3306/tcp on 127.0.0.1 
  15. Discovered open port 631/tcp on 127.0.0.1 
  16. Completed Connect Scan at 12:11, 0.01s elapsed (1000 total ports) 
  17. Initiating Service scan at 12:11 
  18. Scanning 5 services on localhost (127.0.0.1) 
  19. Completed Service scan at 12:11, 6.04s elapsed (5 services on 1 host) 
  20. NSE:Script scanning 127.0.0.1. 
  21. Initiating NSE at 12:11 
  22. Completed NSE at 12:11, 0.22s elapsed 
  23. Nmap scan report for localhost (127.0.0.1) 
  24. Host is up (0.00025s latency). 
  25. Not shown:995 closed ports 
  26. PORT     STATE SERVICE VERSION 
  27. 22/tcp   open  ssh     (protocol 2.0) 
  28. | ssh-hostkey:1024 95:41:c2:46:25:8d:bc:2d:d1:15:c6:90:ca:a7:8b:bc (DSA) 
  29. | 2048 47:32:93:bf:49:df:9c:e7:d7:c5:f8:ef:92:e3:28:c2 (RSA) 
  30. |_256 bd:ef:f2:21:01:b1:cb:78:c7:42:a8:f3:5f:40:e3:37 (ECDSA) 
  31. 25/tcp   open  smtp    Postfix smtpd 
  32. |_smtp-commands:robert-ubuntu1410, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN,  
  33. | ssl-cert:Subject:commonName=ubuntu-kylin 
  34. | Issuer:commonName=ubuntu-kylin 
  35. Public Key type:rsa 
  36. Public Key bits:2048 
  37. Not valid before:2015-10-24T08:56:26+00:00 
  38. Not valid after: 2025-10-21T08:56:26+00:00 
  39. | MD5:  2458 afb6 3955 335a b4ad 171e 3917 b222 
  40. |_SHA-1:eb49 e335 4352 ccd7 4582 aa2d 1002 7eb3 725e 9045 
  41. |_ssl-date:2103-09-27T17:18:12+00:00; +86y157d13h06m52s from local time
  42. 631/tcp  open  ipp     CUPS 1.7 
  43. | http-methods:GET HEAD OPTIONS POST PUT 
  44. | Potentially risky methods:PUT 
  45. |_See http://nmap.org/nsedoc/scripts/http-methods.html 
  46. | http-robots.txt:1 disallowed entry  
  47. |_/ 
  48. |_http-title:Home - CUPS 1.7.2 
  49. 3306/tcp open  mysql   MySQL 5.5.54-0ubuntu0.14.04.1 
  50. | mysql-info:Protocol:10 
  51. | Version:5.5.54-0ubuntu0.14.04.1 
  52. | Thread ID:38 
  53. Some Capabilities:Long Passwords, Connect with DB, Compress, ODBC, Transactions, Secure Connection 
  54. | Status:Autocommit 
  55. |_Salt:yB|ixB~v 
  56. 8080/tcp open  http    Apache Tomcat/Coyote JSP engine 1.1 
  57. |_http-favicon:Unknown favicon MD5:0488FACA4C19046B94D07C3EE83CF9D6 
  58. | http-methods:GET HEAD POST PUT DELETE TRACE OPTIONS PATCH 
  59. | Potentially risky methods:PUT DELETE TRACE PATCH 
  60. |_See http://nmap.org/nsedoc/scripts/http-methods.html 
  61. |_http-title:Site doesn't have a title (application/json;charset=UTF-8). 
  62. 1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at http://www.insecure.org/cgi-bin/servicefp-submit.cgi : 
  63. SF-Port22-TCP:V=6.40%I=7%D=4/23%Time=58FC2968%P=x86_64-pc-linux-gnu%r(NULL 
  64. SF:,2B,"SSH-2\.0-OpenSSH_6\.6\.1p1\x20Ubuntu-2ubuntu2\.8\r\n"); 
  65. Service Info:Host: robert-ubuntu1410 
  66.  
  67. NSE:Script Post-scanning. 
  68. Initiating NSE at 12:11 
  69. Completed NSE at 12:11, 0.00s elapsed 
  70. Read data files from:/usr/bin/../share/nmap 
  71. Service detection performed. Please report any incorrect results at http://nmap.org/submit/ . 
  72. Nmap done:1 IP address (1 host up) scanned in 6.49 seconds 

从上面的输出可以看到,多个端口对外提供服务:

  1. Discovered open port 22/tcp on 127.0.0.1
  2. Discovered open port 8080/tcp on 127.0.0.1
  3. Discovered open port 25/tcp on 127.0.0.1
  4. Discovered open port 3306/tcp on 127.0.0.1
  5. Discovered open port 631/tcp on 127.0.0.1

其中,8080是Vesta发号器对外提供的服务,3306是mysql对外提供的服务。

7 Linux系统高级工具

7.1 pstack

pstack命令用来显示每个进程的调用栈。可以使用pstack来查看进程正在挂起的执行方法,也可以用来查看进程的本地线程堆栈,与JVM的jstack配合可以看到JVM线程运行的全景。

使用方式:


  1. pstack 2862 

命令输出:


  1. pstack 9040 >> /tmp/pstack.log 
  2.  
  3. Thread 289 (Thread 0x7f8928bdb700 (LWP 9041)): 
  4. #0  0x00000032a480ea5d in accept () from /lib64/libpthread.so.0 
  5. #1  0x00007f88735eaad7 in NET_Accept () from /apps/product/jdk1.6.0_19/jre/lib/amd64/libnet.so 
  6. #2  0x00007f88735e6ad0 in Java_java_net_PlainSocketImpl_socketAccept () from /apps/product/jdk1.6.0_19/jre/lib/amd64/libnet.so 
  7. #3  0x00007f8921010c48 in ?? () 
  8. #4  0x00007f88fca90bd8 in ?? () 
  9. #5  0x00007f88fca90c20 in ?? () 
  10. #6  0x0000000000000001 in ?? () 
  11. #7  0x00007f8928bd9c28 in ?? () 
  12. #8  0x0000000000000000 in ?? () 
  13.  
  14. Thread 288 (Thread 0x7f88809fe700 (LWP 9042)): 
  15. #0  0x00000032a480b5bc in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0 
  16. #1  0x00007f89291b6757 in os::PlatformEvent::park() () from /apps/product/jdk1.6.0_19/jre/lib/amd64/server/libjvm.so 
  17. #2  0x00007f892918fc45 in Monitor::IWait(Thread*, long) () from /apps/product/jdk1.6.0_19/jre/lib/amd64/server/libjvm.so 
  18. #3  0x00007f892919040e in Monitor::wait(bool, long, bool) () from /apps/product/jdk1.6.0_19/jre/lib/amd64/server/libjvm.so 
  19. #4  0x00007f8928f413b5 in GCTaskManager::get_task(unsigned int) () from /apps/product/jdk1.6.0_19/jre/lib/amd64/server/libjvm.so 
  20. #5  0x00007f8928f42663 in GCTaskThread::run() () from /apps/product/jdk1.6.0_19/jre/lib/amd64/server/libjvm.so 
  21. #6  0x00007f89291b702f in java_start(Thread*) () from /apps/product/jdk1.6.0_19/jre/lib/amd64/server/libjvm.so 
  22. #7  0x00000032a48079d1 in start_thread () from /lib64/libpthread.so.0 
  23. #8  0x00000032a40e886d in clone () from /lib64/libc.so.6 
  24. ...... 

7.1 strace

系统调用工具,是Linux系统下的一款程序调试工具,用来监控一个应用程序所使用的

系统调用,通过它可以跟踪系统调用,让你熟悉一个Linux程序在背后是怎么工作的。

适用于想研究Linux底层的工作机制,或者JVM和Linux系统本身的bug导致的技术攻关的场景。

由于虚拟机有问题,没有收集到这部分的输出信息 :(

8 /Proc文件系统

Linux系统内核提供了通过/proc文件系统查看运行时内核内部数据结构的能力,也可以改变内核参数设置。

显示CPU信息:


  1. cat /proc/cpuinfo 

显示内存信息:


  1. cat /proc/meminfo 

显示详细的内存映射信息:


  1. cat /proc/zoneinfo 

显示磁盘映射信息:


  1. cat /proc/mounts 

查看系统平均负载命令:


  1. cat /proc/loadavg 

9 性能和压测工具

9.1 ab

ab是一款针对HTTP协议实现的服务进行性能压测的工具,它本来是设计用来测量apache服务器的性能指标,特别是测试阿帕奇服务器每秒能够处理多少请求的指标,以及响应的时间等,但是此命令也可以用来测试一切通用的HTTP协议服务器的性能。

测量HTTP GET协议的接口:


  1. robert@robert-ubuntu1410:~$ ab -c10 -n100000 "http://localhost:8080/genid" 
  2. This is ApacheBench, Version 2.3 <$Revision:1528965 $> 
  3. Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ 
  4. Licensed to The Apache Software Foundation, http://www.apache.org/ 
  5.  
  6. Benchmarking localhost (be patient) 
  7. Completed 10000 requests 
  8. Completed 20000 requests 
  9. Completed 30000 requests 
  10. Completed 40000 requests 
  11. Completed 50000 requests 
  12. Completed 60000 requests 
  13. Completed 70000 requests 
  14. Completed 80000 requests 
  15. Completed 90000 requests 
  16. Completed 100000 requests 
  17. Finished 100000 requests 
  18.  
  19.  
  20. Server Software:       Apache-Coyote/1.1 
  21. Server Hostname:       localhost 
  22. Server Port:           8080 
  23.  
  24. Document Path:         /genid 
  25. Document Length:       19 bytes 
  26.  
  27. Concurrency Level:     10 
  28. Time taken for tests:  30.728 seconds 
  29. Complete requests:     100000 
  30. Failed requests:       0 
  31. Total transferred:     16700000 bytes 
  32. HTML transferred:      1900000 bytes 
  33. Requests per second:   3254.33 [#/sec] (mean) 
  34. Time per request:      3.073 [ms] (mean) 
  35. Time per request:      0.307 [ms] (mean, across all concurrent requests) 
  36. Transfer rate:         530.74 [Kbytes/sec] received 
  37.  
  38. Connection Times (ms) 
  39.               min  mean[+/-sd] median   max 
  40. Connect:       0    0   0.8      0      24 
  41. Processing:    0    3   3.1      2      88 
  42. Waiting:       0    2   2.7      1      80 
  43. Total:         0    3   3.3      2      88 
  44.  
  45. Percentage of the requests served within a certain time (ms) 
  46.   50%      2 
  47.   66%      3 
  48.   75%      4 
  49.   80%      4 
  50.   90%      6 
  51.   95%      9 
  52.   98%     13 
  53.   99%     16 
  54.  100%     88 (longest request) 

从输出中可以看出,开源的Vesta发号器QPS达到3254.33,平均响应时间是3毫秒,所有请求在88毫秒内返回,99%的请求在16毫秒返回。

也可以对使用POST协议的服务进行压测:


  1. ab -c 10 -n 1000 -p post -T  'application/x-www-form-urlencoded'  http://localhost:8080/billing/account/update 

POST文件内容:


  1. accountId=1149983321489408&clientDesc=1 

9.2 jmeter

jmeter是apache组织开发的基于Java的性能压力测试工具。用于对Java开发的软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到通用的性能测试领域。它可以用于测试静态和动态资源,例如静态文件、Java Applet、CGI脚本、Java类库、数据库、FTP服务器,HTTP服务器等等。

jmeter可以用于对服务器、网络或对象模拟巨大的负载,在不同类别的压力下,测试它们的强度和分析整体性能。另外,jmeter能够对应用程序做功能和回归测试,通过创建带有断言的脚本来自动化的验证你的程序满足你期望的结果。为了最大限度的灵活性,jmeter允许使用正则表达式创建断言。

jemeter是一个复杂性能测试工具和平台,开发者需要在自己的平台下集成jmeter,并且开发jemeter的测试用例才能使用,本文不对jmeter做展开,读者可自行通过阅读jmeter主页的文档学习。

9.3 mysqlslap

这是mysql自带的一款性能压测工具,通过模拟多个并发客户端访问mysql来执行压力测试,同时提供了详细的的数据性能报告。此工具可以自动生成测试表和数据,并且可以模拟读、写、混合读写、查询等不同的使用场景,并且能够很好的对比多个存储引擎在相同环境下的并发压力下性能上的差别。

9.3.1 使用单线程测试

使用方式:


  1. mysqlslap -a -uroot -pyouarebest 

命令输出:


  1. robert@robert-ubuntu1410:~$ mysqlslap -a -uroot -pyouarebest 
  2. Benchmark 
  3.     Average number of seconds to run all queries:0.108 seconds 
  4.     Minimum number of seconds to run all queries:0.108 seconds 
  5.     Maximum number of seconds to run all queries:0.108 seconds 
  6.     Number of clients running queries:1 
  7.     Average number of queries per client:0 

这里可以看到,使用单线程连接一次服务器需要108毫秒。

9.3.2 使用100个多线程测试

使用方式:


  1. mysqlslap -a -c 100 -uroot -pyouarebest 

命令输出:


  1. robert@robert-ubuntu1410:~$ mysqlslap -a -c 100 -uroot -pyouarebest 
  2. Benchmark 
  3.     Average number of seconds to run all queries:0.504 seconds 
  4.     Minimum number of seconds to run all queries:0.504 seconds 
  5.     Maximum number of seconds to run all queries:0.504 seconds 
  6.     Number of clients running queries:100 
  7.     Average number of queries per client:0 

这里可以看到,使用多线程连接一次服务器需要504毫秒/100,大约为5毫秒,可见增加并发提高了吞吐量指标。

9.3.3 多次测试对测试结果求平均值

使用方式:


  1. mysqlslap -a -i 10 -uroot -pyouarebest 

命令输出:


  1. robert@robert-ubuntu1410:~$ mysqlslap -a -i 10 -uroot -pyouarebest 
  2. Benchmark 
  3.     Average number of seconds to run all queries:0.108 seconds 
  4.     Minimum number of seconds to run all queries:0.098 seconds 
  5.     Maximum number of seconds to run all queries:0.132 seconds 
  6.     Number of clients running queries:1 
  7.     Average number of queries per client:0 

这里可以看到,多次测试求平均值,可以看到不同次的测试的结果稍有不同,平均为108ms,这与第一个测试结果是相同的。

9.3.4 测试读操作的性能指标

使用方式:


  1. mysqlslap -a -c10 --number-of-queries=1000 --auto-generate-sql-load-type=read -uroot -pyouarebest 

命令输出:


  1. robert@robert-ubuntu1410:~$ mysqlslap -a -c10 --number-of-queries=1000 --auto-generate-sql-load-type=read -uroot -pyouarebest 
  2. Benchmark 
  3.     Average number of seconds to run all queries:0.048 seconds 
  4.     Minimum number of seconds to run all queries:0.048 seconds 
  5.     Maximum number of seconds to run all queries:0.048 seconds 
  6.     Number of clients running queries:10 
  7.     Average number of queries per client:100 

可以算出,平均每个查询需要48毫秒/1000,为0.048毫秒。数据库服务器处理SQL的QPS为1000/0.048秒, 平均QPS为20833次/每秒。

9.3.5 测试写操作的性能指标

使用方式:


  1. mysqlslap -a -c10 --number-of-queries=1000 --auto-generate-sql-load-type=write -uroot -pyouarebest 

命令输出:


  1. robert@robert-ubuntu1410:~$ mysqlslap -a -c10 --number-of-queries=1000 --auto-generate-sql-load-type=write -uroot -pyouarebest 
  2. Benchmark 
  3.     Average number of seconds to run all queries:3.460 seconds 
  4.     Minimum number of seconds to run all queries:3.460 seconds 
  5.     Maximum number of seconds to run all queries:3.460 seconds 
  6.     Number of clients running queries:10 
  7.     Average number of queries per client:100 

可以算出,平均每个写操作需要3460毫秒/1000,为3.4毫秒。数据库服务器处理SQL的QPS为1000/3.46秒, 平均QPS为289次/每秒。

9.3.6 测试读写混合操作的性能指标

使用方式:


  1. mysqlslap -a -c10 --number-of-queries=1000 --auto-generate-sql-load-type=mixed -uroot -pyouarebest 

命令输出:


  1. robert@robert-ubuntu1410:~$ mysqlslap -a -c10 --number-of-queries=1000 --auto-generate-sql-load-type=mixed -uroot -pyouarebest 
  2. Benchmark 
  3.     Average number of seconds to run all queries:1.944 seconds 
  4.     Minimum number of seconds to run all queries:1.944 seconds 
  5.     Maximum number of seconds to run all queries:1.944 seconds 
  6.     Number of clients running queries:10 
  7.     Average number of queries per client:100 

可以算出,平均每个读或写操作需要1944毫秒/1000,为1.9毫秒。数据库服务器处理SQL的QPS为1000/1.944秒, 平均QPS为514次/每秒。

9.3.7 多次不同并发数混合操作的性能指标

测试不同的存储引擎的性能进行对比,执行一次测试,分别50和100个并发,共执行1000次总查询,50和100个并发分别得到一次测试结果,并发数越多,执行完所有查询的时间越长,为了准确起见,可以多次迭代测试后求多次平均值。

使用方式:


  1. mysqlslap -a --concurrency=50,100 --number-of-queries 1000 --debug-info --engine=myisam,innodb --iterations=5 -uroot -pyouarebest 

命令输出:


  1. robert@robert-ubuntu1410:~$ mysqlslap -a --concurrency=50,100 --number-of-queries 1000 --debug-info --engine=myisam,innodb --iterations=5 -uroot -pyouarebest 
  2. Benchmark 
  3.     Running for engine myisam 
  4.     Average number of seconds to run all queries:0.080 seconds 
  5.     Minimum number of seconds to run all queries:0.070 seconds 
  6.     Maximum number of seconds to run all queries:0.106 seconds 
  7.     Number of clients running queries:50 
  8.     Average number of queries per client:20 
  9.  
  10.  
  11. Benchmark 
  12.     Running for engine myisam 
  13.     Average number of seconds to run all queries:0.100 seconds 
  14.     Minimum number of seconds to run all queries:0.075 seconds 
  15.     Maximum number of seconds to run all queries:0.156 seconds 
  16.     Number of clients running queries:100 
  17.     Average number of queries per client:10 
  18.  
  19. Benchmark 
  20.     Running for engine innodb 
  21.     Average number of seconds to run all queries:0.527 seconds 
  22.     Minimum number of seconds to run all queries:0.437 seconds 
  23.     Maximum number of seconds to run all queries:0.801 seconds 
  24.     Number of clients running queries:50 
  25.     Average number of queries per client:20 
  26.  
  27. Benchmark 
  28.     Running for engine innodb 
  29.     Average number of seconds to run all queries:0.608 seconds 
  30.     Minimum number of seconds to run all queries:0.284 seconds 
  31.     Maximum number of seconds to run all queries:0.991 seconds 
  32.     Number of clients running queries:100 
  33.     Average number of queries per client:10 
  34.  
  35.  
  36. User time 0.85, System time 1.28 
  37. Maximum resident set size 14200, Integral resident set size 0 
  38. Non-physical pagefaults 36206, Physical pagefaults 0, Swaps 0 
  39. Blocks in 0 out 0, Messages in 0 out 0, Signals 0 
  40. Voluntary context switches 61355, Involuntary context switches 1244 

从这次测试可以看到,并发数增多,由于有并发就有同步操作的损耗,100并发的响应时间性能指标要略小于50并发的性能指标。

9.4 sysbench

9.4.1 CPU性能测试

使用方式:


  1. sysbench --test=cpu --cpu-max-prime=20000 run 

命令输出:


  1. robert@robert-ubuntu1410:~$ sysbench --test=cpu --cpu-max-prime=20000 run 
  2. sysbench 0.4.12: multi-threaded system evaluation benchmark 
  3.  
  4. Running the test with following options: 
  5. Number of threads:1 
  6.  
  7. Doing CPU performance benchmark 
  8.  
  9. Threads started! 
  10. Done. 
  11.  
  12. Maximum prime number checked in CPU test:20000 
  13.  
  14.  
  15. Test execution summary: 
  16.     total time:                         26.0836s 
  17.     total number of events:             10000 
  18.     total time taken by event execution:26.0795 
  19.     per-request statistics: 
  20.          min:                                 2.41ms 
  21.          avg:                                 2.61ms 
  22.          max:                                 6.29ms 
  23.          approx.  95 percentile:              2.93ms 
  24.  
  25. Threads fairness: 
  26.     events (avg/stddev):          10000.0000/0.00 
  27.     execution time (avg/stddev):  26.0795/0.00 

从这里可以看出做一次素数加法运算平均时间是2.61毫秒。

9.4.2 线程锁性能测试

使用方式:


  1. robert@robert-ubuntu1410:~$ sysbench --test=threads --num-threads=64 --thread-yields=100 --thread-locks=2 run 

命令输出:


  1. robert@robert-ubuntu1410:~$ sysbench --test=threads --num-threads=64 --thread-yields=100 --thread-locks=2 run 
  2. sysbench 0.4.12: multi-threaded system evaluation benchmark 
  3.  
  4. Running the test with following options: 
  5. Number of threads:64 
  6.  
  7. Doing thread subsystem performance test 
  8. Thread yields per test:100 Locks used:2 
  9. Threads started! 
  10. Done. 
  11.  
  12.  
  13. Test execution summary: 
  14.     total time:                         0.6559s 
  15.     total number of events:             10000 
  16.     total time taken by event execution:41.5442 
  17.     per-request statistics: 
  18.          min:                                 0.02ms 
  19.          avg:                                 4.15ms 
  20.          max:                               114.28ms 
  21.          approx.  95 percentile:             23.35ms 
  22.  
  23. Threads fairness: 
  24.     events (avg/stddev):          156.2500/36.13 
  25.     execution time (avg/stddev):  0.6491/0.00 

可见,在64个线程中,每个线程yield 100次,并且上锁2次,每次事件需要4毫秒的时间。

9.4.3 磁盘随机IO性能测试

用sysbench工具可以测试顺序读,顺序写,随机读,随机写等磁盘IO性能:


  1. sysbench --test=fileio --file-num=16 --file-total-size=100M prepare 
  2. sysbench --test=fileio --file-total-size=100M --file-test-mode=rndrd --max-time=180 --max-requests=100000000 --num-threads=16 --init-rng=on --file-num=16 --file-extra-flags=direct --file-fsync-freq=0 --file-block-size=16384 run  
  3. sysbench --test=fileio --file-num=16 --file-total-size=2G cleanup 

命令输出:


  1. robert@robert-Latitude-E6440:~/tmp$ sysbench --test=fileio --file-num=16 --file-total-size=100M prepare 
  2. sysbench 0.4.12: multi-threaded system evaluation benchmark 
  3.  
  4. 16 files, 6400Kb each, 100Mb total 
  5. Creating files for the test... 
  6.  
  7. robert@robert-Latitude-E6440:~/tmp$ sysbench --test=fileio --file-total-size=100M --file-test-mode=rndrd --max-time=180 --max-requests=100000000 --num-threads=16 --init-rng=on --file-num=16 --file-extra-flags=direct --file-fsync-freq=0 --file-block-size=16384 run 
  8. sysbench 0.4.12: multi-threaded system evaluation benchmark 
  9.  
  10. Running the test with following options: 
  11. Number of threads:16 
  12. Initializing random number generator from timer. 
  13.  
  14.  
  15. Extra file open flags:16384 
  16. 16 files, 6.25Mb each 
  17. 100Mb total file size 
  18. Block size 16Kb 
  19. Number of random requests for random IO:100000000 
  20. Read/Write ratio for combined random IO test:1.50 
  21. Calling fsync() at the end of test, Enabled. 
  22. Using synchronous I/O mode 
  23. Doing random read test 
  24. Threads started! 
  25. Time limit exceeded, exiting... 
  26. (last message repeated 15 times) 
  27. Done. 
  28.  
  29. Operations performed: 43923 Read, 0 Write, 0 Other = 43923 Total 
  30. Read 686.3Mb  Written 0b  Total transferred 686.3Mb  (3.8104Mb/sec) 
  31.   243.86 Requests/sec executed 
  32.  
  33. Test execution summary: 
  34.     total time:                         180.1126s 
  35.     total number of events:             43923 
  36.     total time taken by event execution:2880.7789 
  37.     per-request statistics: 
  38.          min:                                 0.13ms 
  39.          avg:                                65.59ms 
  40.          max:                              1034.24ms 
  41.          approx.  95 percentile:            223.33ms 
  42.  
  43. Threads fairness: 
  44.     events (avg/stddev):          2745.1875/64.44 
  45.     execution time (avg/stddev):  180.0487/0.03 
  46.  
  47. robert@robert-Latitude-E6440:~/tmp$ sysbench --test=fileio --file-num=16 --file-total-size=2G cleanup 
  48. sysbench 0.4.12: multi-threaded system evaluation benchmark 
  49.  
  50. Removing test files... 

上面测试显示,这台机器随机IO速度3M/s,IOPS高达243.86。

9.4.4 内存性能测试

使用方式:


  1. robert@robert-ubuntu1410:~$ sysbench --test=memory --memory-block-size=16k --memory-total-size=16K run 

命令输出:

由于虚拟机有问题,没有收集到这部分的输出信息 :(

9.4.4 MYSQL事务性操作测试

由于prepare阶段不能自动创建schema,需要手工预先创建测试使用的schema,并且使用--mysql-db=test来指定。

使用方式:


  1. sysbench --test=oltp --mysql-table-engine=myisam --oltp-table-size=1000 --mysql-user=root --mysql-host=localhost --mysql-password=youarebest --mysql-db=test  run 

命令输出:


  1. robert@robert-ubuntu1410:/etc/mysql$ sysbench --test=oltp --mysql-table-engine=myisam --oltp-table-size=1000 --mysql-user=root --mysql-host=localhost --mysql-password=youarebest --mysql-db=test  prepare 
  2. sysbench 0.4.12: multi-threaded system evaluation benchmark 
  3.  
  4. No DB drivers specified, using mysql 
  5. Creating table 'sbtest'... 
  6. Creating 1000 records in table 'sbtest'... 
  7.  
  8. robert@robert-ubuntu1410:/etc/mysql$ sysbench --test=oltp --mysql-table-engine=myisam --oltp-table-size=1000 --mysql-user=root --mysql-host=localhost --mysql-password=youarebest --mysql-db=test  run 
  9. sysbench 0.4.12: multi-threaded system evaluation benchmark 
  10.  
  11. No DB drivers specified, using mysql 
  12. Running the test with following options: 
  13. Number of threads:1 
  14.  
  15. Doing OLTP test. 
  16. Running mixed OLTP test 
  17. Using Special distribution (12 iterations,  1 pct of values are returned in 75 pct cases) 
  18. Using "LOCK TABLES WRITE" for starting transactions 
  19. Using auto_inc on the id column 
  20. Maximum number of requests for OLTP test is limited to 10000 
  21. Threads started! 
  22. Done. 
  23.  
  24. OLTP test statistics: 
  25.     queries performed: 
  26.         read:                           140000 
  27.         write:                          50000 
  28.         other:                          20000 
  29.         total:                          210000 
  30.     transactions:                       10000  (689.49 per sec.) 
  31.     deadlocks:                          0      (0.00 per sec.) 
  32.     read/write requests:                190000 (13100.32 per sec.) 
  33.     other operations:                   20000  (1378.98 per sec.) 
  34.  
  35. Test execution summary: 
  36.     total time:                         14.5035s 
  37.     total number of events:             10000 
  38.     total time taken by event execution:14.4567 
  39.     per-request statistics: 
  40.          min:                                 0.92ms 
  41.          avg:                                 1.45ms 
  42.          max:                                19.34ms 
  43.          approx.  95 percentile:              2.52ms 
  44.  
  45. Threads fairness: 
  46.     events (avg/stddev):          10000.0000/0.00 
  47.     execution time (avg/stddev):  14.4567/0.00 
  48.  
  49. robert@robert-ubuntu1410:/etc/mysql$ sysbench --test=oltp --mysql-table-engine=myisam --oltp-table-size=1000 --mysql-user=root --mysql-host=localhost --mysql-password=youarebest --mysql-db=test  cleanup 
  50. sysbench 0.4.12: multi-threaded system evaluation benchmark 
  51.  
  52. No DB drivers specified, using mysql 
  53. Dropping table 'sbtest'... 
  54. Done. 

从测试结果中得出事务TPS为689次/秒,读写的QPS为13100次/秒,每个请求处理的平均时间是1.45毫秒。

9.5 dd

dd可以用于测试磁盘顺序IO的存取速度,在应用场景中,打印日志通常表现为顺序IO的写操作,而数据库查询多为磁盘随机IO。

在磁盘上放一个文件,然后使用如下命令:


  1. dd if=/home/robert/test-file of=/dev/null bs=512 count=10240000 

从结果中就能看出这个磁盘的顺序IO的读取速度:


  1. robert@robert-Latitude-E6440:~/working/multimedia-test$ dd if=./bigfile.tar of=/dev/null bs=512 count=10240000 
  2. 记录了160+0 的读入 
  3. 记录了160+0 的写出 
  4. 81920字节(82 kB)已复制,0.0277534 秒,3.0 MB/秒 
  5. robert@robert-Latitude-E6440:~/working/multimedia-test$ dd if=./bigfile.tar of=/dev/null bs=512 count=10240000 
  6. 记录了160+0 的读入 
  7. 记录了160+0 的写出 
  8. 81920字节(82 kB)已复制,0.000345242 秒,237 MB/秒 
  9. robert@robert-Latitude-E6440:~/working/multimedia-test$ dd if=./bigfile.tar of=/dev/null bs=512 count=10240000 
  10. 记录了160+0 的读入 
  11. 记录了160+0 的写出 
  12. 81920字节(82 kB)已复制,0.000238306 秒,344 MB/秒 

从上面的测试中发现,文件的顺序读取可以达到上百兆字节,第一次只有3兆,这是因为第一次操作系统的IO缓存没有命中导致的。普通x86机器上顺序读在100M左右,IBM或者华为的高端机器可以达到1G/s。

10 摘要命令

10.1 md5sum

用于生成md5摘要,通常用于文件上传和下载操作校验内容的正确性,或者通过加盐的hmac做对称数据签名。

为文件生成md5摘要:


  1. robert@robert-ubuntu1410:~$ md5sum test.txt  
  2. 23cdc18507b52418db7740cbb5543e54  test.txt 

10.2 sha256

由于md5摘要算法可以通过碰撞的方法进行破解,虽然,碰撞后数据还能符合业务规则的可能性比较小,但是安全无小事,大家都倾向于使用更安全的sha256算法。

通常也用于文件上传和下载操作校验正确性,或者通过加盐的sha256-hmac做对称数据签名。

为文件生成sha256摘要:


  1. robert@robert-ubuntu1410:~$ sha256sum test.txt  
  2. 2634c3097f98e36865f0c572009c4ffd73316bc8b88ccfe8d196af35f46e2394  test.txt 

10.3 base64

base64编码是网络上最常见的用于传输8位字节代码的编码方式之一,这种编码可以保证所输出的编码位全都是可读字符,base64制定了一个编码表,以便进行统一转换。编码表共有64个字符,因此称为base64编码。

base64编码把3个8位字节(38=24)转化为4个6位的字节(46=24),之后在6位的前面补两个0,形成8位一个字节的形式。如果剩下的字符不足3个字节,则用0填充,输出字符使用'=',因此编码后输出的文本末尾可能会出现1个或者2个'='。

把文件内容转化成base64编码:


  1. robert@robert-ubuntu1410:~$ base64 test.txt  
  2. MTIzNDU2NzgK 

另外,区块链里面存储秘钥的时候并没有使用base64编码,而是使用了base58编码,去除了肉眼容易混淆的可见字符,例如:去除了'I',因为它和数字'1'相似,去掉了字母'o',因为它和数字0相似,从这里可以看到一款产品是如何从用户的角度思考和设计的。

11 命令与场景汇总表

Java服务化系统线上应急和技术攻关,你必须掌握的Linux命令

Java服务化系统线上应急和技术攻关,你必须掌握的Linux命令

Java服务化系统线上应急和技术攻关,你必须掌握的Linux命令

Java服务化系统线上应急和技术攻关,你必须掌握的Linux命令

12 总结经验

本文全面介绍了线上应急和技术攻关必不可少的基础Linux命令和工具,包括:查看活动进程的命令、内存监控命令、CPU使用情况监控命令、磁盘IO监控命令、网络查看和监控命令、Linux系统高级工具、Proc文件系统、性能压测工具、生成摘要的命令和工具等。

在文章末尾,对本文介绍的命令进行了总结,并且汇入了一个表格,表格可以用来帮助查找不同场景使用哪些命令能够解决特定的问题,读者可以把此表格打印出来,放在桌面上,需要的时候瞄一眼,就可以找到相应命令来定位问题。

正如本文开头描述的一样,如果有想了解在互联网公司里线上应急和技术攻关过程中常用的应用层脚本和Java虚拟机命令,请参考上一篇文章《Java服务化系统线上应急和技术攻关,你必须拥有的那些应用层脚本和Java虚拟机命令》,这两篇文章是解决线上应急和技术攻关过程中定位问题的姊妹篇。


作者:李艳鹏

来源:51CTO

上一篇:燃!Java全球标准中国人参与制定,阿里成首个受邀中国公司


下一篇:如何安装 SAP Commerce Cloud,以便让 SAP Spartacus 使用