1、JVM的启动参数
我是这样设置的:
java -Xmx1024m -Xms1024m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m
启动tomcat之后,使用 jmap -heap `pgrep -u root java`,得到如下信息:
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 1073741824 (1024.0MB)
NewSize = 1048576 (1.0MB)
MaxNewSize = 4294901760 (4095.9375MB)
OldSize = 4194304 (4.0MB)
NewRatio = 4
SurvivorRatio = 4
PermSize = 12582912 (12.0MB)
MaxPermSize = 16777216 (16.0MB)
Heap Usage:
New Generation (Eden + 1 Survivor Space):
capacity = 178913280 (170.625MB)
used = 51533904 (49.14656066894531MB)
free = 127379376 (121.47843933105469MB)
28.80384508070055% used
Eden Space:
capacity = 143130624 (136.5MB)
used = 51533904 (49.14656066894531MB)
free = 91596720 (87.35343933105469MB)
36.00480635087569% used
From Space:
capacity = 35782656 (34.125MB)
used = 0 (0.0MB)
free = 35782656 (34.125MB)
0.0% used
To Space:
capacity = 35782656 (34.125MB)
used = 0 (0.0MB)
free = 35782656 (34.125MB)
0.0% used
tenured generation:
capacity = 859045888 (819.25MB)
used = 1952984 (1.8625106811523438MB)
free = 857092904 (817.3874893188477MB)
0.22734338494383202% used
Perm Generation:
capacity = 12582912 (12.0MB)
used = 6656024 (6.347679138183594MB)
free = 5926888 (5.652320861816406MB)
52.897326151529946% used
------------------------------------------华丽的分割线---------------------------------------
-Xmx1024m -Xms1024m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m
-Xmx1024m 最大堆内存为 1024M
-Xms1024m 初始堆内存为 1024M
-XX:NewRatio=4
则 年轻代:年老代=1:4 1024M/5=204.8M
故 年轻代=204.8M 年老代=819.2M
-XX:SurvivorRatio=4
则年轻代中 2Survivor:1Eden=2:4 204.8M/6=34.13333333333333M
故 Eden=136.5333333333333M 1Suivivor=34.13333333333333M
用 jmap -heap <pid>
查看的结果 与我们计算的结果一致
-----------------------------------华丽的分割线-------------------------------------------
3、编写测试页面
在网站根目录里新建页面perf.jsp,内容如下:
<%intsize = (int)(1024 * 1024 * m);byte[] buffer = new byte[size];Thread.sleep(s);%>
注:m值用来设置每次申请内存的大小,s 表示睡眠多少ms
4、使用jstat来监控内存变化
这里使用 jstat -gcutil `pgrep -u root java` 1500 10
再解释一下,这里有三个参数:
·pgrep -u root java --> 得到java的进程ID号
·1500 --> 表示每隔1500ms取一次数据
·10 --> 表示一共取10次数据
5、用ab来进行压测
压测的命令:[root@CentOS ~]# ab -c150 -n50000 "http://localhost/perf.jsp?m=1&s=10"
注:这里使用150个线程并发访问,一共访问50000次。
默认情况下你可以使用 http://localhost:8080/perf.jsp?m=1&s=10 来访问。
--------------------------------------------华丽的分割线----------------------------------------
下面开始进行实验:
·先启动Java内存的监听:
[root@CentOS ~]# jstat -gcutil 8570 1500 10
·在开启一个终端,开始压测:
[root@CentOS ~]# ab -c150 -n50000 "http://localhost/perf.jsp?m=1&s=10"
两个命令结束之后的结果如下:
jstat:
[root@CentOS ~]# jstat -gcutil 8570 1500 10
S0 S1 E O P YGC YGCT FGC FGCT GCT
0.06 0.00 53.15 2.03 67.18 52 0.830 1 0.218 1.048
0.00 0.04 18.46 2.03 67.18 55 0.833 1 0.218 1.052
0.03 0.00 28.94 2.03 67.18 56 0.835 1 0.218 1.053
0.00 0.04 34.02 2.03 67.18 57 0.836 1 0.218 1.054
0.04 0.00 34.13 2.03 67.18 58 0.837 1 0.218 1.055
0.00 0.04 38.62 2.03 67.18 59 0.838 1 0.218 1.056
0.04 0.00 8.39 2.03 67.18 60 0.839 1 0.218 1.058
0.04 0.00 8.39 2.03 67.18 60 0.839 1 0.218 1.058
0.04 0.00 8.39 2.03 67.18 60 0.839 1 0.218 1.058
0.04 0.00 8.39 2.03 67.18 60 0.839 1 0.218 1.058
结果简单解析:
可以看到JVM里S0和S1始终有一个是空的,Eden区达到一定比例之后就会产生Minor GC,由于我这里的Old Generation 区设置的比较大,所以没有产生Full GC。
ab
[root@CentOS ~]# ab -c150 -n50000 "http://localhost/perf.jsp?m=1&s=10"
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 5000 requests
Completed 10000 requests
Completed 15000 requests
Completed 20000 requests
Completed 25000 requests
Completed 30000 requests
Completed 35000 requests
Completed 40000 requests
Completed 45000 requests
Finished 50000 requests
Server Software: Apache/2.2.3
Server Hostname: localhost
Server Port: 80
Document Path: /perf.jsp?m=1&s=10
Document Length: 979 bytes
Concurrency Level: 150
Time taken for tests: 13.467648 seconds
Complete requests: 50000
Failed requests: 0
Write errors: 0
Non-2xx responses: 50005
Total transferred: 57605760 bytes
HTML transferred: 48954895 bytes
Requests per second: 3712.60 [#/sec] (mean)
Time per request: 40.403 [ms] (mean) #平均请求时间
Time per request: 0.269 [ms] (mean, across all concurrent requests)
Transfer rate: 4177.05 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 46.5 0 3701
Processing: 10 38 70.3 36 6885
Waiting: 3 35 70.3 33 6883
Total: 10 39 84.4 37 6901
Percentage of the requests served within a certain time (ms)
50% 37
66% 38
75% 39
80% 39
90% 41
95% 43
98% 50
99% 58
100% 6901 (longest request)
step1:安装JDK
1.1 sudo sh jdk-6u10-linux-i586.bin
1.2 sudo gedit /etc/environment
export JAVA_HOME=/home/linkin/Java/jdk1.6.0_23
export JRE_Home=/home/linkin/Java/jdk1.6.0_23/jre
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
1.3 sudo gedit /etc/profile
在umask 022之前添加以下语句:
export JAVA_HOME=/home/linkin/Java/jdk1.6.0_23
export JRE_HOME=/home/linkin/Java/jdk1.6.0_23/jre
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH:$HOME/bin
更改时区:
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
安装NTP:
yum install ntp
安装后执行
ntpdate cn.pool.ntp.org
即可同步国际时间..
开机后自动同步时间:
vi /etc/rc.d/rc.local中,最下面添加
ntpdate cn.pool.ntp.org
关闭IPV6
在/etc/sysctl.conf结尾添加
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
重启服务器
删除IPV6的DNS服务器
step2:SSH免密码登陆
2.1 首先在master主机上,linkin
@master :~$ ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
2.2 linkin
@master :~$ cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys 将id_dsa.pub写入authorized_keys
2.3 linkin
@master :~/.ssh$ scp id_dsa.pub linkin@192.168.149.2:/home/linkin
2.4 登陆到linkin主机 $cat id_dsa.pub >> .ssh/authorized_keys
authorized_keys的权限要是600。chmod 600 .ssh/authorized_keys 2.5 在Datenode上执行同样的操作就能实现彼此无密码登陆
step3:安装hadoop
3.1 设置hadoop-env.sh
export JAVA_HOME=/home/linkin/jdk1.6.0_10
3.2 配置core-site.xml
<property>
<name>hadoop.tmp.dir</name>
<value>/home/linkin/hadoop-0.20.2/tmp</value>
<description>A base for other temporary directories.</description>
</property>
<property>
<name>fs.default.name</name>
<value>hdfs://master:9000</value>//要写主机名
</property> 3.3 配置hdfs-site.xml
<property>
<name>dfs.replication</name>
<value>1</value>
</property> 3.4 配置mapred-site.xml
<property>
<name>mapred.job.tracker</name>
<value>master:9001</value>//要写主机名
</property>

3.5 配置master和slaves
master:master(主机名)slaves:linkin(主机名)这2个配置文件可以不拷贝到其它机器上,只在master上保存即可。
3.6 配置hosts文件
127.0.0.1 localhost (注意这里不能放其他的如机器名,否则会使hbase的master名称变成localhost) 192.168.149.7 master
192.168.149.2 linkin
3.7 配置profile,在末尾追加以下内容,并输入source/etc/profile使之生效
export JAVA_HOME=/home/linkin/jdk1.6.0_10
export JRE_HOME=/home/linkin/jdk1.6.0_10/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$PATH
HADOOP设置
export HADOOP_HOME=/home/linkin/hadoop-0.20.2
export PATH=$HADOOP_HOME/bin:$PATH
//export PATH=$PATH:$HIVE_HOME/bin
3.8 将hadoop-0.20.2拷贝到其它主机对应的目录下。将/ect/profile和/etc/hosts也拷贝到其它机器上。profile需要做生效操作。
step4 格式化HDFS
bin/hadoop namenode -format
bin/hadoop dfs -ls
step5 启动hadoop
bin/start-all.sh
查看HDFS http://192.168.149.7:50070
查看JOB状态 http://192.168.149.7:50030/jobtracker.jsp
参考资源:
http://wiki.ubuntu.org.cn/%E5%88%A9%E7%94%A8Cloudera%E5%AE%9E%E7%8E%B0Hadoop
如果要读一堆的文本文件到数据库,则可以使用SPRIN BATCH。
主流程:
由JobRunner启动Job,Job启动Step,Step启动TaskLet,TaskLet启动Chunk,Chunk启动ItemRader/ItemProcessor/ItemWriter。
Step之间可以设定流程,即在Step间放一个Decision,在上一步放一个Listener,根据条件把某变量值放到Context中,Decision根据此值决定下一步是哪个。
DefaultLineMapper:将STRING转成MAP
DelimitedLineTokenizer:将行以豆号分割出来放到LIST
BeanWrapperFieldSetMapper:将MAP转成VO
FlatFileItemWriter:输出到文件
DelimitedLineAggregator:对象转字符串
自定义TaskLet:如果任务不是读或写那种,就新增自定义类完成所需工作
http://www.cnblogs.com/gulvzhe/archive/2011/11/06/2238125.html http://www.ibm.com/developerworks/cn/java/j-lo-springbatch1/http://www.visa4uk.fco.gov.uk/Welcome.htm
前言
接触Hadoop有两年的时间了,期间遇到很多的问题,既有经典的NameNode和JobTracker内存溢出故障,也有HDFS存储小文件问题,既有任务调度问题,也有MapReduce性能问题.遇到的这些问题有些是Hadoop自身的缺陷(短板),有些则是使用的不当。
在解决问题的过程中,有时需要翻源码,有时会向同事、网友请教,遇到复杂问题则会通过mail list向全球各地Hadoop使用者,包括Hadoop Committer(Hadoop开发者)求助。在获得很多人帮助后,自己将遇到问题和心得整理成文,希望本文可以对那些焦头烂额的Hadoop新手们有所帮助,少走笔者的弯路。
PS. 本文基于 Cloudera CDH 3u4(同Apache Hadoop 1.0)编写。相关推荐配置为官方推荐值或者笔者经验数值,它不是绝对的,可能会因为不同的应用场景和硬件环境有所出入。
1. 选择Cloudera CDH部署你的Cluster动机
大多数管理员都是从Apache Hadoop开始学习。笔者最开始也使用Apache版本Hadoop进行开发和部署工作,但接触到Cloudera CDH后,我发现它可以使管理员的工作更简单,不仅可以获得最新的特性和Bug修复,有时也会带来令人惊喜的性能改善。
CDH为什么更好?笔者罗列了以下几点:
CDH基于稳定版Apache Hadoop,并应用了最新Bug修复或者Feature的Patch。Cloudera常年坚持季度发行Update版本,年度发行Release版本,更新速度比Apache官方快,而且在实际使用过程中CDH表现无比稳定,并没有引入新的问题。
Cloudera官方网站上安装、升级文档详细,省去Google时间。
CDH支持Yum/Apt包,Tar包,RPM包,Cloudera Manager四种方式安装,总有一款适合您。官方网站推荐Yum/Apt方式安装,笔者体会其好处如下: 联网安装、升级,非常方便。当然你也可以下载rpm包到本地,使用Local Yum方式安装。
自动下载依赖软件包,比如要安装Hive,则会级联下载、安装Hadoop。
Hadoop生态系统包自动匹配,不需要你寻找与当前Hadoop匹配的Hbase,Flume,Hive等软件,Yum/Apt会根据当前安装Hadoop版本自动寻找匹配版本的软件包,并保证兼容性。
自动创建相关目录并软链到合适的地方(如conf和logs等目录);自动创建hdfs, mapred用户,hdfs用户是HDFS的最高权限用户,mapred用户则负责mapreduce执行过程中相关目录的权限。
推荐指数:★★★
推荐理由:获取最新特性和最新Bug修复;安装维护方便,节省运维时间。
2. Hadoop集群配置与管理安装和维护Hadoop集群涉及大量的管理工作,包括软件安装,设备管理(crontab、iptables等)、配置分发等。
对于小型集群软件分发和节点管理可以使用PDSH这款软件,它可以通过免密钥的SSH将文件分发到目标服务器,以及为一组目标设备发送命令并获得反馈。如果是大型集群或者硬件配置差别很大的集群,推荐使用puppet这样的工具帮助你维护配置文件,或者通过Cloudera Manager以GUI的方式的管理集群(注意:Clodera Manager不是开源软件,免费版最多支持50个节点)。
推荐指数:★★★
推荐理由:提高运维效率
3. 开启SecondaryNameNodeSecondaryNameNode(下称SNN)的主要功能是工作是帮助NameNode(下称NN)合并编辑日志,然后将合并后的镜像文件copy回NN,以减少NN重启时合并编辑日志所需的时间。SNN不是NN的热备,但是通过以下步骤可以实现将SNN切换为NN的目的。首先,SNN节点上导入从NN Copy过来的镜像文件,然后修改SNN机器名和IP与NN一致,最后重启集群。
特别注意的是SNN的内存配置要与NN一致,因为合并编辑日志的工作需要将metadata加载到内存完成。另外,不仅仅是SNN,任何保存NN镜像的节点都可以通过上面步骤变为NN,只是SNN更适合罢了。
推荐指数:★★★
推荐理由:减少NN重启导致集群服务中断时间;NN节点故障后,SNN充当NN角色
4. 使用Ganglia和Nagios监控你的集群当运行一个大型mapreduce 作业时,我们通常非常关心该作业对TaskTracker(下称TT)CPU、内存、磁盘,以及整个网络的带宽情况,这时候就需要Ganglia这个工具为我们生成相关图表来诊断、分析问题。
Ganglia可以监控集群状态,但当你的服务器down机或者某个TT挂掉,它却无法通知到你,这时我们可以使用Nagios这款告警软件,它可以配置邮件告警和短息告警。通过编写plugins,可以实现自己的监控功能。我们的集群目前做了如下监控:
NameNode、JobTracker内存
DataNode和TaskTracker运行状态
NFS服务状态
磁盘使用情况
服务器负载状态
推荐指数:★★★
推荐理由:Ganglia可以帮你记录集群状态,方便诊断问题;Nagios可以再遇到问题时第一时间通知你。
5. 设置好内存至关重要Hadoop集群安装完毕后,第一件事就是修改bin/hadoop-evn.sh文件设置内存。主流节点内存配置为32GB,典型场景内存设置如下
NN: 15-25 GB JT:2-4GB DN:1-4 GB TT:1-2 GB,Child VM 1-2 GB 集群的使用场景不同相关设置也有不同,如果集群有大量小文件,则要求NN内存至少要20GB,DN内存至少2GB。
推荐指数:★★★★★
推荐理由:几个组件中NN对内存最为敏感,它有单点问题,直接影响到集群的可用性;JT同样是单点,如果JT内存溢出则所有MapReduce Job都无法正常执行。
6. 管理员玩转MapReduceHadoop原生MapReduce需要Java语言编写,但是不会Java也没问题,通过Hadoop streaming框架管理员可以使用Python,Shell,Perl等语言进行MapReduce开发,但更简单的办法是安装和使用Hive或者Pig。
推荐指数:★★★
推荐理由:减少运维时间,快速响应各种ad-hot需求和故障诊断。
7. NameNode HA前面已经说过,NN是整个集群可能出现的单点故障。
Hadoop通过在hdfs.site.xml文件的dfs.name.dir属性指定保持的metadata路径,如果希望保持到多个路径,可以使用逗号分割配置多个路径。
dfs.name.dir /data/cache1/dfs/nn,/data/cache2/dfs/nn Hadoop官方推荐配置为metadata配置多个path,其中包含一个NFS的路径。但根据笔者一次集群严重故障经验,即使这样,还是导致了所有镜像文件损坏,包括SNN上的镜像文件,所以定期备份一个可用的副本还是很有必要的。
推荐指数:★★★★★
推荐理由:Cloudera3uX和Apache1.0的NN单点问题是大家最头痛问题之一,多些准备,少许痛苦。
8. 使用firewall阻止坏人进入Hadoop的安全控制非常简单,只包含简单的权限,即只根据客户端用户名,决定使用权限。它的设计原则是:“避免好人做错事,但不阻止坏人做坏事”。
如果你知道某台NN的IP和端口,则可以很轻松获取HDFS目录结构,并通过修改本机机器用户名伪装成HDFS文件所属owner,对该文件进行删除操作。
通过配置kerberos,可以实现身份验证。但很多管理员使用更简单有效的办法——通过防火墙对访问IP进行控制。
推荐指数:★★★★★
推荐理由:安全无小事,防范于未然。
9. 开启垃圾箱(trash)功能动机
我曾经犯下一个错误,在我加班非常累,大脑稍有混乱的时候,不小心删除执行了一个命令“hadoop fs -rmr /xxx/xxx”,没有删除提示,几TB的数据,一下子就没有了。简直让我崩溃,后悔莫及。这时你多希望有个时间机器可以让HDFS恢复到删除前的状态。
trash功能就是这个时间机器, 它默认是关闭的,开启后,被你删除的数据将会mv到操作用户目录的".Trash"文件夹,可以配置超过多长时间,系统自动删除过期数据。这样一来,当操作失误的时候,可以把数据mv回来。开启垃圾箱步骤如下:
vi core-site.xml ,添加下面配置,value单位为分钟。
fs.trash.interval 1440 笔者 在CDH3u4下不用重启Namenode就可以生效。开启垃圾箱后,如果希望文件直接被删除,可以在使用删除命令时添加“–skipTrash” 参数,如下:
hadoop fs –rm –skipTrash /xxxx推荐指数:★★★★★
推荐理由:想要时间机器吗?
10. 去社区寻找帮助Hadoop是一个非常优秀的开源项目,但它仍存有很多尚未解决的问题,诸如,NN,JT单点问题,JT挂死问题,Block在小文件下汇报效率低下等问题。此时可以通过如下渠道找到可以帮助你的人,笔者几次集群严重故障都是通过Cloudera公司的google user group直接获得几位 committer的帮助。通常前一天提问,第二天就会有反馈。下面是两个能够帮助的你的社区,当然你也可以帮助其他人:
Apache hadoop的mail list :
http://hadoop.apache.org/mailing_lists.html
Cloudera CDH google group:
https://groups.google.com/a/cloudera.org/forum/#!forum/cdh-user
推荐指数:★★★★★
推荐理由:没有人比软件作者更熟悉Hadoop本身,去社区求助,帮你解决很多自己无法跨越的问题。
Cloudera简介:公司是一家Hadoop软件服务公司,提供免费软件CDH和Cloudera Manager Free Edition,同时提供Hadoop相关资讯、培训、技术支持等服务。Hadoop创始人Dong Cutting在该公司任架构师,同时该公司拥有多名Apache Committer。