pinpoint 安装部署

序章

pinpoint是开源在github上的一款APM监控工具,它是用Java编写的,用于大规模分布式系统监控。它对性能的影响最小(只增加约3%资源利用率),安装agent是无侵入式的,只需要在被测试的Tomcat中加上3句话,打下探针,就可以监控整套程序了。这篇Blog主要是想记录一下它安装的过程,方便日后查阅。

 

我安装它用到的2台 CentOS6.8 虚拟机,一台主要部署pinpoint的主程序,一台模拟测试环境。配置如下:

IP 操作系统 安装项 描述
192.168.245.136 CentOS 6.8 pinpoint pinpoint的web展示端,逻辑控制机,以及Hbase存储
192.168.245.135 CentOS 6.8 pinpoint-agent 主要用来采集数据,发送给pinpoint处理

 

java 1.7 http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html

pinpoint https://github.com/naver/pinpoint

我将需要的资源都整合起来了,上传至百度网盘

百度网盘: <链接: http://pan.baidu.com/s/1eRU5RW2 密码: u89p>

 

下面是官方的一些截图,很帅,很直观

demo0

 

demo1

demo2

demo3

 

 

1. 环境配置

 

1.1 获取需要的依赖包

进入home目录,创建一个”pp_res”的资源目录,用来存放需要安装的包

mkdir /home/pp_res
cd /home/pp_res/

使用xshell等类似的工具,将需要的文件上传到Linux虚拟机中,主要要传的文件都在百度网盘

  1. jdk7 — Java运行环境
  2. hbase-1.0 — 数据库,用来存储监控信息
  3. tomcat8.0 — Web服务器
  4. pinpoint-collector.war — pp的控制器
  5. pinpoint-web.war — pp展示页面
  6. pp-collector.init — 用来快速启动pp-col,不要也可以
  7. pp-web.init — 用来快速启动pp-web,不要也可以

xshell

 

使用ll命令,查看一下是否上传成功

[root@localhost pp_res]# ll
total 367992
-rw-r–r–. 1 root root   9277365 Nov 15 00:07 apache-tomcat-8.0.36.tar.gz
-rw-r–r–. 1 root root 103847513 Nov 15 00:07 hbase-1.0.3-bin.tar.gz
-rw-r–r–. 1 root root 153512879 Nov 15 00:07 jdk-7u79-linux-x64.tar.gz
-rw-r–r–. 1 root root   6621915 Nov 15 00:07 pinpoint-agent-1.5.2.tar.gz
-rw-r–r–. 1 root root  31339914 Nov 15 00:07 pinpoint-collector-1.5.2.war
-rw-r–r–. 1 root root  54505168 Nov 15 00:07 pinpoint-web-1.5.2.war
-rw-r–r–. 1 root root      3084 Nov 15 00:07 pp-collector.init
-rw-r–r–. 1 root root      3072 Nov 15 00:07 pp-web.init
-rw-r–r–. 1 root root  17699306 Nov 15 00:07 zookeeper-3.4.6.tar.gz

1.2 配置jdk1.7

这套APM系统主要是用jdk1.7来进行部署的,首先要配置jdk的环境变量

cd /home/pp_res/
tar -zxvf jdk-7u79-linux-x64.tar.gz
mkdir /usr/java
mv jdk1.7.0_79/ /usr/java/jdk17

配置java环境变量

vi /etc/profile

将下列复制到profile的最后一行中

export JAVA_HOME=/usr/java/jdk17
export PATH=$PATH:$JAVA_HOME/bin

让环境变量生效

source /etc/profile

测试java的环境变量是否配置好了

[root@localhost pp_res]# java -version
java version “1.7.0_79”
Java(TM) SE Runtime Environment (build 1.7.0_79-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)

2. 安装Hbase

pinpoint收集来的测试数据,主要是存在Hbase数据库的。所以它可以收集大量的数据,可以进行更加详细的分析。

2.1 将Hbase解压,并且放入指定目录

cd /home/pp_res/
tar -zxvf hbase-1.0.3-bin.tar.gz
mkdir -p /data/service
mv hbase-1.0.3/ /data/service/hbase

2.2 修改hbase-env.sh的JAVA_HOME环境变量位置

cd /data/service/hbase/conf/
vi hbase-env.sh

在27行左右的位置,修改如下

export JAVA_HOME=/usr/java/jdk17/

2.3 修改Hbase的配置信息

vi hbase-site.xml

在结尾修改成如下,这里我们指定Hbase本地来存储数据,生产环境将数据建议存入HDFS中。

<configuration>
  <property>
    <name>hbase.rootdir</name>
    <value>file:///data/hbase</value>
 </property>
</configuration>

2.4 启动hbase

cd /data/service/hbase/bin
./start-hbase.sh

查看Hbase是否启动成功,如果启动成功的会看到”HMaster”的进程

[root@localhost bin]# jps
12075 Jps
11784 HMaster

2.5 初始化Hbase的pinpoint库

执行pinpoint提供的Hbase初始化语句,这时会初始化一会。

./hbase shell /home/pp_res/hbase-create.hbase

执行完了以后,进入Hbase

./hbase shell

进入后可以看到Hbase的版本,还有一些相关的信息

2016-11-15 01:55:44,861 WARN  [main] util.NativeCodeLoader: Unable to load native-hadoop library for your platform… using built
in-java classes where applicableHBase Shell; enter ‘help<RETURN>’ for list of supported commands.
Type “exit<RETURN>” to leave the HBase Shell
Version 1.0.3, rf1e1312f9790a7c40f6a4b5a1bab2ea1dd559890, Tue Jan 19 19:26:53 PST 2016
 
hbase(main):001:0>

输入”status ‘detailed'”可以查看刚才初始化的表,是否存在

hbase(main):001:0> status ‘detailed’
version 1.0.3
0 regionsInTransition
master coprocessors: []
1 live servers
    localhost:50887 1478538574709
        requestsPerSecond=0.0, numberOfOnlineRegions=498, usedHeapMB=24, maxHeapMB=237, numberOfStores=626, numberOfStorefiles=0, storefileUncom
pressedSizeMB=0, storefileSizeMB=0, memstoreSizeMB=0, storefileIndexSizeMB=0, readRequestsCount=7714, writeRequestsCount=996, rootIndexSizeKB=0, totalStaticIndexSizeKB=0, totalStaticBloomSizeKB=0, totalCompactingKVs=0, currentCompactedKVs=0, compactionProgressPct=NaN, coprocessors=[MultiRowMutationEndpoint]        “AgentEvent,,1478539104778.aa1b3b14d0b48d83cbf4705b75cb35b7.”
            numberOfStores=1, numberOfStorefiles=0, storefileUncompressedSizeMB=0, storefileSizeMB=0, memstoreSizeMB=0, storefileIndexSizeMB=0,
readRequestsCount=0, writeRequestsCount=0, rootIndexSizeKB=0, totalStaticIndexSizeKB=0, totalStaticBloomSizeKB=0, totalCompactingKVs=0, currentCompactedKVs=0, compactionProgressPct=NaN, completeSequenceId=-1, dataLocality=0.0

也可以登录web,来查看HBase的数据是否初始化成功

HbaseWeb : http://192.168.245.134:16010/master-status

HbaseWeb

3. 安装pinpoint-collector

 

3.1 部署war包

解压Tomcat,将Tomcat重命名移动到指定位置

cd /home/pp_res/
tar -zxvf apache-tomcat-8.0.36.tar.gz
mv apache-tomcat-8.0.36/ /data/service/pp-col

 

修改pp-col的Tomcat的配置,主要修改端口,避免与pp-web的Tomcat的端口冲突。我在原本默认的端口前都加了1,下面是替换的shell命令。

【注意】最后一条是将tomcat的私有ip开放,需要将localhost替换成本机的ip,我本机的网卡是默认的,如果你本机的网卡不是eth0,需要进行相关的修改。或者直接用”vi”进去,修改localhost

cd /data/service/pp-col/conf/
sed -i ‘s/port=”8005″/port=”18005″/g’ server.xml
sed -i ‘s/port=”8080″/port=”18080″/g’ server.xml
sed -i ‘s/port=”8443″/port=”18443″/g’ server.xml
sed -i ‘s/port=”8009″/port=”18009″/g’ server.xml
sed -i ‘s/redirectPort=”8443″/redirectPort=”18443″/g’ server.xml
sed -i “s/localhost/`ifconfig eth0 | grep ‘inet addr’ | awk ‘{print $2}’ | awk -F: ‘{print $2}’`/g” server.xml

 

部署pinpoint-collector.war包

【注意:如果没有unzip命令,可以 “yum install unzip” 】

cd /home/pp_res/
rm -rf /data/service/pp-col/webapps/*
unzip pinpoint-collector-1.5.2.war -d /data/service/pp-col/webapps/ROOT

 

启动Tomcat

cd /data/service/pp-col/bin/
./startup.sh

 

查看日志,是否成功启动

tail -f ../logs/catalina.out

3.2 配置快速启动

配置快速启动需要修改pp-collector.init的路径( pp-collector在网盘里面有 ),可以”vi”进去,大概在18,24,27行处,修改相关的路径。我这边为了方便,直接就用替换的shell做了,如果路径与我的不一致,需要将路径修改成自己的路径。

cd /home/pp_res
sed -i “s/JAVA_HOME=\/usr\/java\/default\//JAVA_HOME=\/usr\/java\/jdk17\//g” pp-collector.init
sed -i “s/CATALINA_HOME=\/data\/service\/pinpoint-collector\//CATALINA_HOME=\/data\/service\/pp-col\//g” pp-collector.init
sed -i “s/CATALINA_BASE=\/data\/service\/pinpoint-collector\//CATALINA_BASE=\/data\/service\/pp-col\//g” pp-collector.init

 

将文件赋予”执行”的权限,把它放到”init.d”中去。以后就可以restart快速重启了。

chmod 711 pp-collector.init
mv pp-collector.init /etc/init.d/pp-col
 
 
# 测试一下restart
[root@localhost pp_res]# /etc/init.d/pp-col restart
Stoping Tomcat
Using CATALINA_BASE:   /data/service/pp-col/
Using CATALINA_HOME:   /data/service/pp-col/
Using CATALINA_TMPDIR: /data/service/pp-col//temp
Using JRE_HOME:        /usr/java/jdk17/
Using CLASSPATH:       /data/service/pp-col//bin/bootstrap.jar:/data/service/pp-col//bin/tomcat-juli.jar
 
waiting for processes to exitStarting tomcat
Using CATALINA_BASE:   /data/service/pp-col/
Using CATALINA_HOME:   /data/service/pp-col/
Using CATALINA_TMPDIR: /data/service/pp-col//temp
Using JRE_HOME:        /usr/java/jdk17/
Using CLASSPATH:       /data/service/pp-col//bin/bootstrap.jar:/data/service/pp-col//bin/tomcat-juli.jar
Tomcat started.
Tomcat is running with pid: 22824

4. 安装pinpoint-web

4.1 部署war包

解压Tomcat,将Tomcat重命名移动到指定位置

cd /home/pp_res/
tar -zxvf apache-tomcat-8.0.36.tar.gz
mv apache-tomcat-8.0.36/ /data/service/pp-web

 

修改pp-web的Tomcat的配置,主要修改端口,避免与pp-col的Tomcat的端口冲突。我在原本默认的端口前都加了2,下面是替换的shell命令

【注意】最后一条是将tomcat的私有ip开放,需要将localhost替换成本机的ip,我本机的网卡是默认的,如果你本机的网卡不是eth0,需要进行相关的修改。或者直接用”vi”进去,修改localhost

cd /data/service/pp-web/conf/
sed -i ‘s/port=”8005″/port=”28005″/g’ server.xml
sed -i ‘s/port=”8080″/port=”28080″/g’ server.xml
sed -i ‘s/port=”8443″/port=”28443″/g’ server.xml
sed -i ‘s/port=”8009″/port=”28009″/g’ server.xml
sed -i ‘s/redirectPort=”8443″/redirectPort=”28443″/g’ server.xml
sed -i “s/localhost/`ifconfig eth0 | grep ‘inet addr’ | awk ‘{print $2}’ | awk -F: ‘{print $2}’`/g” server.xml

 

部署pinpoint-collector.war包

【注意:如果没有unzip命令,可以 “yum install unzip” 】

cd /home/pp_res/
rm -rf /data/service/pp-web/webapps/*
unzip pinpoint-web-1.5.2.war -d /data/service/pp-web/webapps/ROOT

 

查看war包是否解压成功

[root@localhost conf]# ll /data/service/pp-web/webapps/ROOT/WEB-INF/classes/
total 88
-rw-rw-r–. 1 root root 2164 Apr  7  2016 applicationContext-cache.xml
-rw-rw-r–. 1 root root 3649 Apr  7  2016 applicationContext-dao-config.xml
-rw-rw-r–. 1 root root 1490 Apr  7  2016 applicationContext-datasource.xml
-rw-rw-r–. 1 root root 6680 Apr  7  2016 applicationContext-hbase.xml
-rw-rw-r–. 1 root root 1610 Apr  7  2016 applicationContext-websocket.xml
-rw-rw-r–. 1 root root 6576 Apr  7  2016 applicationContext-web.xml
drwxrwxr-x. 2 root root 4096 Apr  7  2016 batch
-rw-rw-r–. 1 root root  106 Apr  7  2016 batch.properties
drwxrwxr-x. 3 root root 4096 Apr  7  2016 com
-rw-rw-r–. 1 root root  682 Apr  7  2016 ehcache.xml
-rw-rw-r–. 1 root root 1001 Apr  7  2016 hbase.properties
-rw-rw-r–. 1 root root  153 Apr  7  2016 jdbc.properties
-rw-rw-r–. 1 root root 3338 Apr  7  2016 log4j.xml
drwxrwxr-x. 2 root root 4096 Apr  7  2016 mapper
-rw-rw-r–. 1 root root 1420 Apr  7  2016 mybatis-config.xml
drwxrwxr-x. 3 root root 4096 Apr  7  2016 org
-rw-rw-r–. 1 root root  630 Apr  7  2016 pinpoint-web.properties
-rw-rw-r–. 1 root root  141 Apr  7  2016 project.properties
-rw-rw-r–. 1 root root 3872 Apr  7  2016 servlet-context.xml
drwxrwxr-x. 2 root root 4096 Apr  7  2016 sql

这里说明一下:

  • hbase.properties 配置我们pp-web从哪个数据源获取采集数据,这里我们只指定Hbase的zookeeper地址。
  • jdbc.properties pp-web连接自身Mysql数据库的连接认证配置。
  • sql目录 pp-web本身有些数据需要存放在MySQL数据库中,这里需要初始化一下表结构。
  • pinpoint-web.properties 这里pp-web集群的配置文件,如果你需要pp-web集群的话。
  • applicationContext-* .xml 这些文件在后续的调优工作中会用到。
  • log4j.xml 日志相关配置。

 

启动Tomcat

cd /data/service/pp-web/bin/
./startup.sh

 

查看日志,Tocmat是否启动成功

tail -f ../logs/catalina.out

 

日志中出现下面这句话,说明已经启动成功了

org.apache.catalina.startup.Catalina.start Server startup in 79531 ms

这时候我们可以访问一下这个地址,在浏览器中输入”http://192.168.245.136:28080″,就会出现主页面了

如果访问不了的话,关闭防火墙

[root@localhost conf]# /etc/init.d/iptables stop
iptables: Setting chains to policy ACCEPT: filter          [  OK  ]
iptables: Flushing firewall rules:                         [  OK  ]
iptables: Unloading modules:                               [  OK  ]

pp-web

4.2 配置快速启动

需要修改”pp-web.init”,与上面的步骤一致

cd /home/pp_res
sed -i “s/JAVA_HOME=\/usr\/java\/default\//JAVA_HOME=\/usr\/java\/jdk17\//g” pp-web.init
sed -i “s/CATALINA_HOME=\/data\/service\/pinpoint-web\//CATALINA_HOME=\/data\/service\/pp-web\//g” pp-web.init
sed -i “s/CATALINA_BASE=\/data\/service\/pinpoint-web\//CATALINA_BASE=\/data\/service\/pp-web\//g” pp-web.init

 

将文件赋予”执行”的权限,把让放到”init.d”中去。以后就可以restart快速重启了。

chmod 711 pp-web.init
mv pp-web.init /etc/init.d/pp-web
 
 
# 测试一下restart
[root@localhost pp_res]# /etc/init.d/pp-web restart
Stoping Tomcat
Using CATALINA_BASE:   /data/service/pp-web/
Using CATALINA_HOME:   /data/service/pp-web/
Using CATALINA_TMPDIR: /data/service/pp-web//temp
Using JRE_HOME:        /usr/java/jdk17/
Using CLASSPATH:       /data/service/pp-web//bin/bootstrap.jar:/data/service/pp-web//bin/tomcat-juli.jar
 
waiting for processes to exitStarting tomcat
Using CATALINA_BASE:   /data/service/pp-web/
Using CATALINA_HOME:   /data/service/pp-web/
Using CATALINA_TMPDIR: /data/service/pp-web//temp
Using JRE_HOME:        /usr/java/jdk17/
Using CLASSPATH:       /data/service/pp-web//bin/bootstrap.jar:/data/service/pp-web//bin/tomcat-juli.jar
Tomcat started.
Tomcat is running with pid: 22703

5. 部署pp-agent采集监控数据

5.1 在测试系统中,部署pp-agent采集监控数据

 

部署采集器就很简单了,只需要加3句话就好了。我这边做一个测试的Tomcat,来模拟部署。

首先,先建立一个文件夹,放测试需要的包

mkdir /home/pp_test
cd /home/test

 

将测试需要的pp-agent拉到服务器上

pp-test

查看包是否上传成功

[root@localhost pp_test]# ll
total 16820
-rw-r–r–. 1 root root 9277365 Nov  9 02:25 apache-tomcat-8.0.36.tar.gz
-rw-r–r–. 1 root root 6621915 Nov  9 02:25 pinpoint-agent-1.5.2.tar.gz
-rw-r–r–. 1 root root 1320206 Nov  9 02:25 test.war

5.2 配置模拟的Tomcat测试环境

为了方便观察,配置一个假的系统,解压Tomcat到指定目录

cd /home/pp_test
mkdir /data
tar -zxvf apache-tomcat-8.0.36.tar.gz

 

配置localhost让外部可以访问

cd /data/pp-test/conf/
sed -i “s/localhost/`ifconfig eth0 | grep ‘inet addr’ | awk ‘{print $2}’ | awk -F: ‘{print $2}’`/g” server.xml

 

解压测试用的war包

cd /home/pp_test/
rm -rf /data/pp-test/webapps/*
unzip test.war -d /data/pp-test/webapps/ROOT

5.3 配置pp-agent采集器

解压pp-agent

cd /home/pp_test
tar -zxvf pinpoint-agent-1.5.2.tar.gz
mv pinpoint-agent-1.5.2 /data/pp-agent

 

编辑配置文件

cd /data/pp-agent/
vi pinpoint.config

 

主要修改IP,只需要指定到安装pp-col的IP就行了,安装pp-col启动后,自动就开启了9994,9995,9996的端口了。这里就不需要操心了,如果有端口需求,要去pp-col的配置文件(“pp-col/webapps/ROOT/WEB-INF/classes/pinpoint-collector.properties”)中,修改这些端口

profiler.collector.ip=192.168.245.136

 

修改测试项目下的tomcat启动文件”catalina.sh”,修改这个只要是为了监控测试环境的Tomcat,增加探针

cd /data/pp-test/bin
vi catalina.sh

 

在20行增加如下字段

  1. 第一行是pp-agent的jar包位置
  2. 第二行是agent的ID,这个ID是唯一的,我是用pp + 今天的日期命名的,只要与其他的项目的ID不重复就好了
  3. 第三行是采集项目的名字,这个名字可以随便取,只要各个项目不重复就好了
CATALINA_OPTS=”$CATALINA_OPTS -javaagent:/data/pp-agent/pinpoint-bootstrap-1.5.2.jar”
CATALINA_OPTS=”$CATALINA_OPTS -Dpinpoint.agentId=pp20161122″
CATALINA_OPTS=”$CATALINA_OPTS -Dpinpoint.applicationName=MyTestPP

5.4 监控Tomcat

 

配置好了。就可以开始监控了,我们启动测试用的Tomcat的服务器

cd /data/pp-test/bin/
./startup.sh

 

查看启动日志,确实Tomcat启动

tail -f ../logs/catalina.out

 

启动了,我们就可以访问测试环境了

test

test1

这时候我们在访问pp-web,可以发现它的下拉框中,多了一个app

pp-testApp

pp-testView

 

因为我访问了两次,所以他显示有两条请求记录,可以在右上角的框查看详情。

【注意】鼠标点击右上角箭头位置,鼠标左键按住不动,拉框查看。我被这个坑,坑懵逼了,特此写清楚。

pp-detail

 

这时候就弹出了新页面,可以看到,我访问了一次主页,访问了一次test的servlet。而且详细信息都记录在下表中。

pp-code

总结

到这里,整个部署过程就完了。值得要注意的地方:

  1. 如果Hbase不是与pp-web, pp-col装在一台机器上,需要安装zookeeper,只要安装就好,确实2181端口启动就好。
  2. 如果zookeeper安装在独立机器上,这里需要修改一下pp-colletor 和 pp-web的配置文件pinpoint-collector.properties,pinpoint-web.properties,不然会导致俩个模块启动失败。
  3. 发现pinpoint还是有些缺陷,异步的操作监控不到,比如我写了个多线程来发送HttpClient4的请求,但是pinpoint监控不到。但是它介绍又说可以监控到Httpclient4的请求。现在都是分布式系统,异步拿数据再常见不过来,如果监控不到异步的操作,就很鸡肋了。看pp1.6会不会修复这个问题
  4. 在pp1.6部署,Hbase中的默认字段有增加,如果没有加上默认字段,取得的数据就会变得相当少了。

ORACLE常用性能监控SQL

Temp表空间上进程的查询

1
2
3
4
5
select a.tablespace, b.sid, b.serial#, a.blocks,c.sql_text
  from v$sort_usage a,v$session b,v$sqltext c
 where a.session_addr = b.saddr
   and b.sql_address = c.address
 order by a.tablespace,b.sid,b.serial#,c.address, c.piece;

查看表锁

1
select * from sys.v_$sqlarea where disk_reads>100;

监控事例的等待

1
2
3
4
select event,sum(decode(wait_Time,0,0,1)) "Prev",
sum(decode(wait_Time,0,1,0)) "Curr",count(*) "Tot"
from v$session_Wait
group by event order by 4 ;

回滚段的争用情况

1
2
3
select name, waits, gets, waits/gets "Ratio"
from v$rollstat a, v$rollname b
where a.usn = b.usn;

查看前台正在发出的SQL语句

1
2
3
4
5
select user_name,sql_text
   from v$open_cursor
   where sid in (select sid from (select sid,serial#,username,program
   from v$session
   where status='ACTIVE'));

数据表占用空间大小情况

1
2
3
4
select segment_name,tablespace_name,bytes,blocks
from user_segments
where segment_type='TABLE'
ORDER BY bytes DESC ,blocks DESC;

查看表空间碎片大小

1
2
3
4
select tablespace_name,round(sqrt(max(blocks)/sum(blocks))*
          (100/sqrt(sqrt(count(blocks)))),2) FSFI
   from dba_free_space
   group by tablespace_name order by 1;

查看表空间占用磁盘情况

1
2
3
4
5
6
7
8
9
10
11
select
         b.file_id                                 文件ID号,
         b.tablespace_name                         表空间名,
         b.bytes                                 字节数,
         (b.bytes-sum(nvl(a.bytes,0)))                 已使用,
         sum(nvl(a.bytes,0))                         剩余空间,
         sum(nvl(a.bytes,0))/(b.bytes)*100         剩余百分比
         from dba_free_space a,dba_data_files b
         where a.file_id=b.file_id
         group by b.tablespace_name,b.file_id,b.bytes
         order by b.file_id;

查看Oracle 表空间使用率

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
SELECT D.TABLESPACE_NAME, 
       SPACE || 'M' "SUM_SPACE(M)"
       SPACE - NVL (FREE_SPACE, 0) || 'M' "USED_SPACE(M)"
       ROUND ( (1 - NVL (FREE_SPACE, 0) / SPACE) * 100, 2) || '%'
          "USED_RATE(%)"
       FREE_SPACE || 'M' "FREE_SPACE(M)"
  FROM SELECT TABLESPACE_NAME, 
                 ROUND (SUM (BYTES) / (1024 * 1024), 2) SPACE
                 SUM (BLOCKS) BLOCKS 
            FROM DBA_DATA_FILES 
        GROUP BY TABLESPACE_NAME) D, 
       SELECT TABLESPACE_NAME, 
                 ROUND (SUM (BYTES) / (1024 * 1024), 2) FREE_SPACE 
            FROM DBA_FREE_SPACE 
        GROUP BY TABLESPACE_NAME) F 
 WHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME(+) 
UNION ALL                                                           --如果有临时表空间 
SELECT D.TABLESPACE_NAME, 
       SPACE || 'M' "SUM_SPACE(M)"
       USED_SPACE || 'M' "USED_SPACE(M)"
       ROUND (NVL (USED_SPACE, 0) / SPACE * 100, 2) || '%' "USED_RATE(%)"
       NVL (FREE_SPACE, 0) || 'M' "FREE_SPACE(M)"
  FROM SELECT TABLESPACE_NAME, 
                 ROUND (SUM (BYTES) / (1024 * 1024), 2) SPACE
                 SUM (BLOCKS) BLOCKS 
            FROM DBA_TEMP_FILES 
        GROUP BY TABLESPACE_NAME) D, 
       SELECT TABLESPACE_NAME, 
                 ROUND (SUM (BYTES_USED) / (1024 * 1024), 2) USED_SPACE, 
                 ROUND (SUM (BYTES_FREE) / (1024 * 1024), 2) FREE_SPACE 
            FROM V$TEMP_SPACE_HEADER 
        GROUP BY TABLESPACE_NAME) F 
 WHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME(+) 
ORDER BY 1;

查看Temp 表空间实际使用磁盘大小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Select f.tablespace_name,
       d.file_name "Tempfile name",
       round((f.bytes_free + f.bytes_used) / 1024 / 1024, 2) "total MB",
       round(((f.bytes_free + f.bytes_used) - nvl(p.bytes_used, 0)) / 1024 / 1024,
             2) "Free MB",
       round(nvl(p.bytes_used, 0) / 1024 / 1024, 2) "Used MB",
       round((round(nvl(p.bytes_used, 0) / 1024 / 1024, 2) /
             round((f.bytes_free + f.bytes_used) / 1024 / 1024, 2)) * 100,
             2) as "Used_Rate(%)"
  from SYS.V_$TEMP_SPACE_HEADER f,
       DBA_TEMP_FILES           d,
       SYS.V_$TEMP_EXTENT_POOL  p
 where f.tablespace_name(+) = d.tablespace_name
   and f.file_id(+) = d.file_id
   and p.file_id(+) = d.file_id;

查看session使用回滚段

1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT  r.name 回滚段名,
        s.sid,
        s.serial#,
        s.username 用户名,
        t.status,
        t.cr_get,
        t.phy_io,
        t.used_ublk,
        t.noundo,
        substr(s.program, 1, 78) 操作程序
FROM   sys.v_$session s,sys.v_$transaction t,sys.v_$rollname r
WHERE  t.addr = s.taddr and t.xidusn = r.usn
ORDER  BY t.cr_get,t.phy_io;

查看SGA区剩余可用内存

1
2
3
4
5
6
select name,
      sgasize/1024/1024        "Allocated(M)",
      bytes/1024            "**空间(K)",
      round(bytes/sgasize*100, 2)   "**空间百分比(%)"
   from   (select sum(bytes) sgasize from sys.v_$sgastat) s, sys.v_$sgastat f
   where  f.name = 'free memory';

–监控表空间I/O比例
select df.tablespace_name name,df.file_name “file”,f.phyrds pyr,
f.phyblkrd pbr,f.phywrts pyw, f.phyblkwrt pbw
from v$filestat f, dba_data_files df
where f.file# = df.file_id
order by df.tablespace_name;

监控SGA命中率

1
2
3
4
5
6
7
select a.value + b.value "logical_reads",
       c.value "phys_reads",
       round(100 * ((a.value+b.value)-c.value) / (a.value+b.value)) "BUFFER HIT RATIO"
from v$sysstat a, v$sysstat b, v$sysstat c
where a.statistic# = 38 and
      b.statistic# = 39 and
      c.statistic# = 40 ;

监控 SGA 中字典缓冲区的命中率

1
2
3
4
5
select parameter, gets,Getmisses , getmisses/(gets+getmisses)*100 "miss ratio",
(1-(sum(getmisses)/ (sum(gets)+sum(getmisses))))*100 "Hit ratio"
from v$rowcache
where gets+getmisses <>0
group by parameter, gets, getmisses ;

监控 SGA **享缓存区的命中率,应该小于1%

1
2
3
select sum(pins) "Total Pins", sum(reloads) "Total Reloads",
sum(reloads)/sum(pins) *100 libcache
from v$librarycache;

监控 SGA 中重做日志缓存区的命中率,应该小于1%

1
2
3
4
5
SELECT name, gets, misses, immediate_gets, immediate_misses,
Decode(gets,0,0,misses/gets*100) ratio1,
Decode(immediate_gets+immediate_misses,0,0,
immediate_misses/(immediate_gets+immediate_misses)*100) ratio2
FROM v$latch WHERE name IN ('redo allocation', 'redo copy');

监控内存和硬盘的排序比率,最好使它小于 .10

1
2
3
SELECT name, value
FROM v$sysstat
WHERE name IN ('sorts (memory)', 'sorts (disk)') ;

监控字典缓冲区

1
2
SELECT SUM(GETS) "DICTIONARY GETS",SUM(GETMISSES) "DICTIONARY CACHE GET MISSES"
FROM V$ROWCACHE ;

系统用户建在system表空间中的表”>非系统用户建在SYSTEM表空间中的表

1
2
3
4
SELECT owner,table_name
FROM DBA_TABLES
WHERE tablespace_name in('SYSTEM','USER_DATA') AND
      owner NOT IN('SYSTEM','SYS','OUTLN', 'ORDSYS','MDSYS','SCOTT', 'HOSTEAC');

性能最差的SQL

1
2
3
4
SELECT * FROM ( SELECT PARSING_USER_ID EXECUTIONS,SORTS,COMMAND_TYPE,DISK_READS,sql_text
                FROM v$sqlarea
                ORDER BY disk_reads DESC)
WHERE ROWNUM<100;

读磁盘数超100次的sql

1
select * from sys.v_$sqlarea where disk_reads>100;

最频繁执行的sql

1
select * from sys.v_$sqlarea where executions>100;

查询使用CPU多的用户session

1
2
3
4
5
6
select a.sid,spid,status,substr(a.program,1,40) prog,a.terminal,osuser,value/60/100 value
from v$session a,v$process b,v$sesstat c
where c.statistic#=12 and
      c.sid=a.sid and
      a.paddr=b.addr
order by value desc;

当前每个会话使用的对象数

1
2
3
4
5
SELECT a.sid,s.terminal,s.program,count(a.sid)
FROM V$ACCESS a,V$SESSION s
WHERE a.owner <> 'SYS'AND s.sid = a.sid
GROUP BY a.sid,s.terminal,s.program
ORDER BY count(a.sid) ;

一个可供中小团队参考的微服务架构技术栈

近年,Spring Cloud 俨然已经成为微服务开发的主流技术栈,在国内开发者社区非常火爆。我近年一直在一线互联网公司(携程,拍拍贷等)开展微服务架构实践,根据我个人的一线实践经验和我平时对 Spring Cloud 的调研,我认为 Spring Cloud 技术栈中的有些组件离生产级开发尚有一定距离。比方说 Spring Cloud Config 和 Spring Cloud Sleuth 都是 Pivotal 自研产品,尚未得到大规模企业级生产应用,很多企业级特性缺失(具体见我后文描述)。

另外 Spring Cloud 体系还缺失一些关键的微服务基础组件,比如 Metrics 监控,健康检查和告警等。所以我在参考 Spring Cloud 微服务技术栈的基础上,结合自身的实战落地经验,也结合国内外一线互联网公司(例如 Netflix,点评,携程,Zalando 等)的开源实践,综合提出更贴近国内技术文化特色的轻量级的微服务参考技术栈。希望这个参考技术栈对一线的架构师(或者是初创公司)有一个好的指导,能够少走弯路,快速落地微服务架构。

这个参考技术栈和总体架构如下图所示:

主要包含 11 大核心组件,分别是:

核心支撑组件

  1. 服务网关 Zuul
  2. 服务注册发现 Eureka+Ribbon
  3. 服务配置中心 Apollo
  4. 认证授权中心 Spring Security OAuth2
  5. 服务框架 Spring MVC/Boot

监控反馈组件

  1. 数据总线 Kafka
  2. 日志监控 ELK
  3. 调用链监控 CAT
  4. Metrics 监控 KairosDB
  5. 健康检查和告警 ZMon
  6. 限流熔断和流聚合 Hystrix/Turbine

后续章节我会依次简单介绍这 11 个组件,在《2018 波波的微服务基础架构和实践》课程中,我会对其中的 8 款核心组件的架构设计和生产实践进行深度剖析,感兴趣的同学可以扫描下方二维码了解详情。

核心支撑组件
服务网关 Zuul

2013 年左右,InfoQ 曾经对前 Netflix 架构总监 Adrian Cockcroft 有过一次专访 [附录 1],其中有问 Adrian:“Netflix 开源这么多项目,你认为哪一个是最不可或缺的 (MOST Indispensable)”,Adrian 回答说:“在 NetflixOSS 开源项目中,有一个容易被忽略,但是 Netflix 最强大的基础服务之一,它就是 Zuul 网关服务。Zuul 网关主要用于智能路由,同时也支持认证,区域和内容感知路由,将多个底层服务聚合成统一的对外 API。Zuul 网关的一大亮点是动态可编程,配置可以秒级生效”。从 Adrian 的回答中,我们可以感受到 Zuul 网关对微服务基础架构的重要性。

Zuul 在英文中是一种怪兽,星际争霸中虫族里头也有 Zuul,Netflix 为网关起名 Zuul,寓意看门神兽。

Zuul 网关在 Netflix 经过生产级验证,在纳入 Spring Cloud 体系之后,在社区中也有众多成功的应用。Zuul 网关在携程(日流量超 50 亿),拍拍贷等公司也有成功的落地实践,是微服务基础架构中网关一块的首选。其它开源产品像 Kong 或者 Nginx 等也可以改造支持网关功能,但是较复杂门槛高一点。

Zuul 网关虽然不完全支持异步,但是同步模型反而使它简单轻量,易于编程和扩展,当然同步模型需要做好限流熔断(和限流熔断组件 Hystrix 配合),否则可能造成资源耗尽甚至雪崩效应(cascading failure)。

服务注册发现 Eureka + Ribbon

针对微服务注册发现场景,社区里头的开源产品当中,经过生产级大流量验证的,目前只有 Netflix Eureka 一个,它也已经纳入 Spring Cloud 体系,在社区中有众多成功应用,例如携程 Apollo 配置中心也是使用 Eureka 做软负载。其它产品如 Zookeeper/Etcd/Consul 等,都是比较通用的产品,还需要进一步封装定制才可生产级使用。Eureka 支持跨数据中心高可用,但它是 AP 最终一致系统,不是强一致性系统。

Ribbon 是可以和 Eureka 配套对接的客户端软负载库,在 Eureka 的配合下能够支持多种灵活的动态路由和负载均衡策略。内部微服务直连可以直接走 Ribbon 客户端软负载,网关上也可以部署 Ribbon,这时网关相当于一个具有路由和软负载能力的超级客户端。

Ribbon 是蝴蝶结的意思。

服务配置中心 Apollo

Spring Cloud 体系里头有个 Spring Cloud Config 产品,但是功能远远达不到生产级,只能小规模场景下用,中大规模企业级场景不建议采用。携程框架研发部开源的 Apollo 是一款在携程和其它众多互联网公司生产落地下来的产品,开源两年多,目前在 github 上有超过 4k 星,非常成功,文档齐全也是它的一大亮点,推荐作为企业级的配置中心产品。

Apollo 支持完善的管理界面,支持多环境,配置变更实时生效,权限和配置审计等多种生产级功能。Apollo 既可以用于连接字符串等常规配置场景,也可用于发布开关(Feature Flag)和业务配置等高级场景。在《2018 波波的微服务基础架构和实践》课程中,第二个模块就配置中心相关主题,会深度剖析携程 Apollo 的架构和实践,预计 6 月份推出,欢迎大家关注学习。

阿波罗是希腊神话中太阳神的意思

认证授权中心 Spring Security OAuth2

目前开源社区还没有特别成熟的微服务安全认证中心产品,之前我工作过的一些中大型互联网公司,比如携程,唯品会等,在这一块基本都是定制自研的,但是对一般企业来说,定制自研还是有门槛的。OAuth2 是一种基于令牌 Token 的授权框架,已经得到众多大厂(Google, Facebook, Twitter, Microsoft 等)的支持,可以认为是事实上的微服务安全协议标准,适用于开放平台联合登录,现代微服务安全(包括单页浏览器 App/ 无线原生 App/ 服务器端 WebApp 接入微服务,以及微服务之间调用等场景),和企业内部应用认证授权 (IAM/SSO) 等多种场景。

Spring Security OAuth2 是 Spring Security 基础上的一个扩展,支持四种主要的 OAuth2 Flows,基本可以作为微服务认证授权中心的推荐产品。但是 Spring Security OAuth2 还只是一个框架,不是一个端到端的开箱即用的产品,企业级应用仍需在其上进行定制,例如提供 Web 端管理界面,对接企业内部的用户认证登录系统,使用 Cache 缓存令牌,和微服务网关对接等,才能作为生产级使用。在《2018 波波的微服务基础架构和实践》课程中,第一个模块就是微服务安全架构和实践相关主题,会深度剖析 OAuth2 原理和 Spring Security OAuth2 实践,欢迎大家关注学习。

Spring Security OAuth2 是 Spring Security 框架的一个扩展。

服务框架 Spring/Boot

Spring 可以说是史上最成功的 Web App/API 开发框架之一,它融入了 Java 社区中多年来沉淀下来的最佳实践,虽然有将近 15 年历史,但目前的社区活跃度仍呈上升趋势。Spring Boot 在 Spring 的基础上进一步打包封装,提供更贴心的 Starter 工程,自启动能力,自动依赖管理,基于代码的配置等特性进一步降低接入门槛。另外 Spring Boot 也提供 actuator 这样的生产级监控特性,支持 DevOps 研发模式,它是微服务开发框架的推荐首选。

REST 契约规范 Swagger 和 Spring 有比较好的集成,使得 Spring 也支持契约驱动开发 (Contract Driven Development) 模型。对于一些中大规模的企业,如果业务复杂团队较多,考虑到互操作性和集成成本,建议采用契约驱动开发模型,也就是开发时先定义 Swagger 契约,然后再通过契约生成服务端接口和客户端,再实现服务端业务逻辑,这种开发模型能够标准化接口,降低系统间集成成本,对于多团队协同并行开发非常重要。

监控反馈组件
数据总线 Kafka

最初由 Linkedin 研发并在其内部大规模成功应用,然后在 Apache 上开源的 Kafka,是业内数据总线 (Databus) 一块的标配,几乎每一家互联网公司都可以看到 Kafka 的身影。Kafka 堪称开源项目的一个经典成功案例,其创始人团队从 Linkedin 离职后还专门成立了一家叫 confluent 的企业软件服务公司,围绕 Kafka 周边提供配套和增值服务。在监控一块,日志和 Metrics 等数据可以通过 Kafka 做收集、存储和转发,相当于中间增加了一个大容量缓冲,能够应对海量日志数据的场景。除了日志监控数据收集,Kafka 在业务大数据分析,IoT 等场景都有广泛应用。如果对 Kafka 进行适当定制增强,还可以用于传统消息中间件场景。

Kafka 的特性是大容量,高吞吐,高可用,数据可重复消费,可水平扩展,支持消费者组等。Kafka 尤其适用于不严格要求实时和不丢数据的大数据日志场景。

Kafka 创始人三人组,离开 Linkedin 后,创立了基于 Kafka 的创业公司 Confluent。

日志监控 ELK

<![endif]–>

ELK(ElasticSearch/Logstash/Kibana)是日志监控一块的标配技术栈,几乎每一家互联网公司都可以看到 ELK 的身影,据称携程是国内 ELK 的最大用户,每日增量日志数据量达到 80~90TB。ELK 已经非常成熟,基本上是开箱即用,后续主要的工作在运维、治理和调优。

ELK 一般和 Kafka 配套使用,因为日志分词操作还是比较耗时的,Kafka 主要作为前置缓冲,起到流量消峰作用,抵消日志流量高峰和消费(分词建索引)的不匹配问题。一旦反向索引建立,日志检索是非常快的,所以日志检索快和灵活是 ElasticSearch 的最大亮点。另外 ELK 还有大容量,高吞吐,高可用,可水平扩容等企业级特性。

创业公司起步期,考虑到资源时间限制,调用链监控和 Metrics 监控可以不是第一优先级,但是 ELK 是必须搭一套的,应用日志数据一定要收集并建立索引,基本能够覆盖大部分 Trouble Shooting 场景(业务,性能,程序 bug 等)。

另外用好 ELK 的关键是治理,需要制定一些规则(比如只收集 Warn 级别以上日志),对应用的日志数据量做好监控,否则开发人员会滥用,什么垃圾数据都往 ELK 里头丢,造成大量空间被浪费,严重的还可能造成性能可用性问题。

ELK + Kafka 参考部署架构

调用链监控 CAT

Spring Cloud 支持基于 Zipkin 的调用链监控,我个人基于实践经验认为 Zipkin 还不能算一款企业级调用链监控产品,充其量只能算是一个半成品,很多重要的企业级特性缺失。Zipkin 最早是由 Twitter 在消化 Google Dapper 论文的基础上研发,在 Twitter 内部有较成功应用,但是在开源出来的时候把不少重要的统计报表功能给阉割了(因为依赖于一些比较重的大数据分析平台),只是开源了一个半成品,能简单查询和呈现可视化调用链,但是细粒度的调用性能数据报表没有开源。

Google 大致在 2007 年左右开始研发称为 Dapper 的调用链监控系统,但在远远早于这个时间(大致在 2002 左右),eBay 就已经有了自己的调用链监控系统 CAL(Centralized Application Logging),Google 和 eBay 的设计思路大致相同,但是也有一些差别。CAL 在 eBay 有大规模成功应用,被称为是 eBay 的四大神器之一(另外三个是 DAL,Messaging 和 SOA)。

开源调用链监控系统 CAT 的作者吴其敏(我曾经和他同事,习惯叫他老吴),曾经在 eBay 工作近十年,期间深入消化吸收了 CAL 的设计。2011 年后老吴离开 eBay 去了点评,用三年时间在点评再造了一款调用链监控产品 CAT(Centralized Application Tracking),CAT 具有 CAL 的基因和影子,同时也融入了老吴在点评的探索实践和创新。

CAT 是一款更完整的企业级调用链监控产品,甚至已经接近一个 APM(Application Performance Management)产品的范畴,它不仅支持调用链的查询和可视化,还支持细粒度的调用性能数据统计报表,这块是 CAT 和市面上其它开源调用链监控产品最本质的差异点,实际上开发人员大部分时间用 CAT 是看性能统计报表(主要是 CAT 的 Transaction 和 Problem 报表),这些报表相当于给了开发人员一把尺子,可以自助测量并持续改进应用性能。另外 CAT 还支持应用报错大盘,自助告警等功能,也是企业级监控非常实用的功能。

CAT 在点评,携程,陆金所,拍拍贷等公司有成功落地案例,因为是国产调用链监控产品,界面展示和功能等更契合国内文化,更易于在国内公司落地。个人推荐 CAT 作为微服务调用链监控的首选。

至于社区里头有人提到 CAT 的侵入性问题,我觉得是要一分为二看,有利有弊,有耦合性但是性能更好,一般企业中基础架构团队会使用 CAT 统一为基础组件埋点,开发人员一般不用自己埋点;另外企业用了一款调用链监控产品以后,一般是不会换的,开发人员用习惯就好了,侵入不是大问题。

CAT 的 Transaction 报表

Metrics 监控 KariosDB

除了日志和调用链,Metrics 也是应用监控的重要关注点。互联网应用提倡度量驱动开发(Metrics Driven Development),也就是说开发人员不仅要关注功能实现,做好单元测试(TDD),还要做好业务层(例如注册,登录和下单数等)和应用层(例如调用数,调用延迟等)的监控埋点,这个也是 DevOps(开发即运维)理念的体现,DevOps 要求开发人员必须关注运维需求,监控埋点是一种生产级运维需求。

Metrics 监控产品底层依赖于时间序列数据库(TSDB),最近比较热的开源产品有 Prometheus 和 InfluxDB,社区用户数量和反馈都不错,可以采纳。但是这些产品分布式能力比较弱,定制扩展门槛比较高,一般建议刚起步量不大的公司采用。

如果企业业务和团队规模发展到一定阶段,建议考虑支持分布式能力的时间序列监控产品,例如 KairosDB 或者 OpenTSDB,我本人对这两款产品都有一些实践经验,KariosDB 基于 Cassandra,相对更轻量一点,建议中大规模公司采用,如果你们公司已经采用 Hadoop/HBase,则 OpenTSDB 也是不错选择。

KairosDB 一般也和 Kafka 配套使用,Kafka 作为前置缓冲。另外注意使用 KariosDB 打点的话 tag 的值不能太离散,否则会有查询性能问题,这个和 KariosDB 底层存储结构有关系。Grafana 是 Metrics 展示标配,可以和 KariosDB 无缝集成。

Grafana 是 Metrics 展示标配,和主流时间序列数据库都可以集成

健康检查和告警 ZMon

除了上述监控手段,我们仍需要健康检查和告警系统作为配套的监控手段。ZMon 是德国电商公司 Zalando 开源的一款健康检查和告警平台,具备强大灵活的监控告警能力。ZMon 本质上可以认为是一套分布式监控任务调度平台,它提供众多的 Check 脚本(也可以自己再定制扩展),能够对各种硬件资源或者目标服务(例如 HTTP 端口,Spring 的 Actuator 端点,KariosDB 中的 Metrics,ELK 中的错误日志等等)进行定期的健康检查和告警,它的告警逻辑和策略采用 Python 脚本实现,开发人员可以实现自助式告警。ZMon 同时适用于系统,应用,业务,甚至端用户体验层的监控和告警。

ZMon 分布式监控告警系统架构,底层基于 KairosDB 时间序列数据库

限流熔断和流聚合 Hystrix+Turbine

2010 年左右,Netflix 也饱受分布式微服务系统中雪崩效应(Cascading Failure)的困扰,于是专门启动了一个叫做弹性工程的项目来解决这个问题,Hystrix 就是弹性工程最终落地下来的一个产品。Hystrix 在 Netflix 微服务系统中大规模推广应用后,雪崩效应问题基本得到解决,整个体统更具弹性。

之后 Netflix 把 Hystrix 开源贡献给了社区,短期获得社区的大量正面反馈,目前 Hystrix 在 github 上有超过 1.3 万颗星,据说支持奥巴马总统选举的系统也曾使用 Hystrix 进行限流熔断保护 [参考附录 2],可见限流熔断是分布式系统稳定性的强需求,Netflix 很好的抓住了这个需求并给出了经过生产级验证的解决方案。Hystrix 已经被纳入 Spring Cloud 体系,它是 Java 社区中限流熔断组件的首选(目前还看不到第二个更好的产品)。

Turbine 是和 Hystrix 配套的一个流聚合服务,能够对 Hystrix 监控数据流进行聚合,聚合以后可以在 Hystrix Dashboard 上看到集群的流量和性能情况。

Hystrix 在英文中是豪猪兽的意思,豪猪兽通过身上的刺保护自己,Netflix 为限流熔断组件起名 Hystrix,寓意 Hystrix 能够保护微服务调用。

HTML转图片利器:wkhtmltox

关于wkhtmltox,是一个可以把HTML转换为图片和pdf的工具。

不多介绍了,详见官网 https://wkhtmltopdf.org/

安装步骤

  1. 下载下来是tar.xz文件,首先解压:
    tar -vxf wkhtmltox-0.12.4_linux-generic-amd64.tar.xz
  2. 解压得到一个目录wkhtmltox,把wkhtmltoimage和wkhtmltopdf复制到/usr/bin目录,更改所有者,并增加可执行属性
sudo cp wkhtmltox/bin/wkhtmltopdf /usr/bin/
sudo cp wkhtmltox/bin/wkhtmltoimage /usr/bin/
sudo chown root:root /usr/bin/wkhtmltopdf
sudo chown root:root /usr/bin/wkhtmltoimage
sudo chmod +x /usr/bin/wkhtmltopdf
sudo chmod +x /usr/bin/wkhtmltoimage
  1. 注意事项

有时候为了让程序可以执行这个命令,可能需要配置环境变量
– 编辑配置文件 vi .bashrc
– 添加环境变量 export PATH=$PATH:/opt/wkhtmltox/bin
– 让修改生效 source .bashrc让修改生效

如果网页上的中文,转成图片后变成乱码方块,请安装相关字体 :)

关于使用

执行wkhtmltoimage www.bing.com bing.png,就会在当前目录下生成了一张png图片。

这个命令还可以增加一些参数,比如常用的设置宽高,图片质量等参数
执行wkhtmltoimage --crop-w 410 --width 410 --quality 50 www.bing.com bing2.png看看

说明:
--crop-w 410:截图宽度410px
--width 410:浏览器模拟宽度410px
--quality 50:图片质量(这个值越大,图片质量越高,当然文件也会比较大)

还有更多参数用法,请 wkhtmltoimage -h查看。
HTML转pdf同理,wkhtmltopdf -h

健康生活方式

世界卫生组织对影响健康的因素进行过如下总结
健康 = 60%生活方式 + 15%遗传因素 + 10%社会因素 + 8%医疗因素 + 7%气候因素
由此可见健康的生活方式管理是新兴起的个人健康管理中最重要的一个策略。健康生活方式是需要培养的,培养的主动性在人们自己。生活方式管理的观念就是强调个体对自己的健康负责。
生活方式管理是通过如下措施达成:
1. 教育 传递知识,确立态度,改变行为;
2. 激励 通过正面强化、反面强化、反馈促进、惩罚等措施进行行为矫正。
3. 训练 通过一系列的参与式训练与体验,培训个体掌握行为矫正的技术。
4. 营销 利用社会营销的技术推广健康行为,营造健康的大环境,促进个体改变不健康的行为。
健康生活方式管理核心是养成良好的生活习惯。很长一段时间内都是人们自己制订一系列的健康计划,由执行者靠毅力自觉执行,由于较枯燥难坚持,通常半途而废的居多。随着移动互联网的兴起,健康生活方式管理方法也随之有了改变。一系列的移动互联网健康管理工具为人们提供了不少便利,使得生活方式的养成更有趣,人们也更有动力。

刷牙时间

饭后三分钟是漱口、刷牙的最佳时间。这时候口腔里的食物开始分解食物残渣,产生的酸性物质容易腐蚀牙釉质,使牙齿受到损害。夜晚刷牙比清晨刷牙好。因为,白天吃东西,有的东西会堵塞在牙缝里,如果睡前不刷牙,食物经过一夜发酵腐烂,细菌大量繁殖,产生的乳酸会严重腐蚀牙龈,引起龋齿病(即虫牙)或牙周炎。所以夜晚刷牙好。

牛奶时间

牛奶含有丰富的钙。睡觉前饮用,可补偿夜间血钙的低落状态,保护骨骼。同时,牛奶有催眠的作用。早晨喝杯牛奶补充一上午的蛋白质及能量等让早餐更营养健康。但最好不要只喝牛奶以免浪费优质蛋白被充当直接能量消耗掉,所以吃点面包等含碳水化合物的食品是有必要的。

水果时间

吃水果的最佳时间是饭前一小时。水果属于生食,最好吃生食后再吃熟食。注意,是饭前一小时左右,而不是吃完水果紧接着吃正餐哦!

喝茶时间

喝茶的最佳时间是用餐后一小时后。饭后马上喝热茶,并不是很科学。因为茶中的鞣酸可与食物中的铁结合,变成不溶性的铁盐,干扰人体对铁的吸收。

散步时间

饭后45分钟至一个小时,散步20分钟,热量消耗最大。如果在饭后两小时再散步,效果会更好。注意,最好不要刚吃完就立刻散步。

洗澡时间

每天晚上睡觉前,冲一个温水澡,能使全身的肌肉放松,减轻疲劳,也能减轻压力。

睡眠时间

午睡最好在中午十一点到下午一点之间,特别是对心脏有好处。饭后半个小时就可以上床小睡一会儿,以半个小时到40分钟为最好。晚上,则以十点至十一点上床为佳,因为人的深睡时间在半夜十二点至次日凌晨三点,而人在睡后一个半小时就能进入深睡状态。

锻炼时间

傍晚锻炼最为有益,原因是:人类的体力发挥或身体的适应能力,都以下午或接近黄昏时分为最佳。此时,人的味觉、视觉、听觉等感觉最敏感,全身协调能力最强,尤其是心率与血压都较平稳,最适宜锻炼。