如何避免regionServer宕機

爲什麼regionserver 和Zookeeper的session expired? 可能的原因有
1. 網絡不好。
2. Java full GC, 這會block所有的線程。如果時間比較長,也會導致session expired.
怎麼辦?
1. 將Zookeeper的timeout時間加長。
2. 配置“hbase.regionserver.restart.on.zk.expire” 爲true。 這樣子,遇到ZooKeeper session expired , regionserver將選擇 restart 而不是 abort
具體的配置是,在hbase-site.xml中加入
<property>
<name>zookeeper.session.timeout</name>
<value>90000</value>
<description>ZooKeeper session timeout.
HBase passes this to the zk quorum as suggested maximum time for a
session.  See http://hadoop.apache.org/zookeeper/docs/current/zookeeperProgrammers.html#ch_zkSessions
“The client sends a requested timeout, the server responds with the
timeout that it can give the client. The current implementation
requires that the timeout be a minimum of 2 times the tickTime
(as set in the server configuration) and a maximum of 20 times
the tickTime.” Set the zk ticktime with hbase.zookeeper.property.tickTime.
In milliseconds.
</description>
</property>
<property>
<name>hbase.regionserver.restart.on.zk.expire</name>
<value>true</value>
<description>
Zookeeper session expired will force regionserver exit.
Enable this will make the regionserver restart.
</description>
</property>
爲了避免java full GC suspend thread 對Zookeeper heartbeat的影響,我們還需要對hbase-env.sh進行配置。
export HBASE_OPTS="$HBASE_OPTS -XX:+HeapDumpOnOutOfMemoryError \ -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode"

修改成

export HBASE_OPTS="$HBASE_OPTS -XX:+HeapDumpOnOutOfMemoryError \ -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled \ -XX:+CMSInitiatingOccupancyFraction=70 \ -XX:+UseCMSInitiatingOccupancyOnly -XX:+UseParNewGC -Xmn256m"


同時,當linux的maxfile設置過小時,scan多個列族也會造成regionServer宕機


JVM配置老忘,附帶mark一下

1: heap size
a: -Xmx

指定jvm的最大heap大小,如:-Xmx=2g

b: -Xms

指定jvm的最小heap大小,如:-Xms=2g,高併發應用,建議和-Xmx一樣,防止因爲內存收縮/突然增大帶來的性能影響。

c: -Xmn

指定jvmNew Generation的大小,如:-Xmn256m。這個參數很影響性能,如果你的程序需要比較多的臨時內存,建議設置到512M,如果用的少,儘量降低這個數值,一般來說128/256足以使用了。

d: -XX:PermSize=

指定jvmPerm Generation的最小值,如:-XX:PermSize=32m。這個參數需要看你的實際情況,可以通過jmap命令看看到底需要多少。

e: -XX:MaxPermSize=

指定Perm Generation的最大值,如:-XX:MaxPermSize=64m

f: -Xss

指定線程桟大小,如:-Xss128k,一般來說,webx框架下的應用需要256K。如果你的程序有大規模的遞歸行爲,請考慮設置到512K/1M。這個需要全面的測試才能知道。不過,256K已經很大了。這個參數對性能的影響比較大的。

g: -XX:NewRatio=

指定jvmOld Generation heap sizeNew Generation的比例,在使用CMS GC的情況下此參數失效,如:-XX:NewRatio=2

h: -XX:SurvivorRatio=

指定New GenerationEden Space與一個Survivor Spaceheap size比例,-XX:SurvivorRatio=8,那麼在總共New Generation10m的情況下,Eden Space8m

i: -XX:MinHeapFreeRatio=

指定jvm heap在使用率小於n的情況下,heap進行收縮,Xmx==Xms的情況下無效,如:-XX:MinHeapFreeRatio=30

j: -XX:MaxHeapFreeRatio=

指定jvm heap在使用率大於n的情況下,heap 進行擴張,Xmx==Xms的情況下無效,如:-XX:MaxHeapFreeRatio=70

k: -XX:LargePageSizeInBytes=

指定Java heap的分頁頁面大小, 如:-XX:LargePageSizeInBytes=128m

2: garbage collector
a: -XX:+UseParallelGC

指定在New Generation使用parallel collector,並行收集,暫停,app threads,同時啓動多個垃圾回收thread,不能和CMS gc一起使用。系統噸吐量優先,但是會有較長長時間的app pause,後臺系統任務可以使用此 gc

b: -XX:ParallelGCThreads=

指定parallel collection時啓動的thread個數,默認是物理processor的個數

c: -XX:+UseParallelOldGC

指定在Old Generation使用parallel collector

d: -XX:+UseParNewGC

指定在New Generation使用parallel collector,是UseParallelGCgc的升級版本,有更好的性能或者優點,可以和CMS gc一起使用

e: -XX:+CMSParallelRemarkEnabled

在使用UseParNewGC的情況下,儘量減少mark的時間

f: -XX:+UseConcMarkSweepGC

指定在Old Generation使用concurrent cmark sweep gcgc threadapp thread並行(在init-markremarkpause app thread)。app pause時間較短,適合交互性強的系統,如web server

g: -XX:+UseCMSCompactAtFullCollection

在使用concurrent gc的情況下,防止memory fragmention,對live object進行整理,使memory 碎片減少

h: -XX:CMSInitiatingOccupancyFraction=

指示在old generation 在使用了n%的比例後,啓動concurrent collector,默認值是68,如:-XX:CMSInitiatingOccupancyFraction=70

 

有個bug,在低版本(1.5.09 and early)的jvm上出現,

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6486089

i: -XX:+UseCMSInitiatingOccupancyOnly

指示只有在old generation在使用了初始化的比例後concurrent collector啓動收集

3:others
a: -XX:MaxTenuringThreshold=

指定一個object在經歷了nyoung gc後轉移到old generation區,在linux64java6下默認值是15,此參數對於throughput collector無效,如:-XX:MaxTenuringThreshold=31

b: -XX:+DisableExplicitGC

禁止java程序中的full gc,如System.gc()的調用。最好加上麼,防止程序在代碼裏誤用了。對性能造成衝擊。

c: -XX:+UseFastAccessorMethods

getset方法轉成本地代碼

d: -XX:+PrintGCDetails

打應垃圾收集的情況如:

[GC 15610.466: [ParNew: 229689K->20221K(235968K), 0.0194460 secs] 1159829K->953935K(2070976K), 0.0196420 secs]

e: -XX:+PrintGCTimeStamps

打應垃圾收集的時間情況,如:

[Times: user=0.09 sys=0.00, real=0.02 secs]

f: -XX:+PrintGCApplicationStoppedTime

打應垃圾收集時,系統的停頓時間,如:

Total time for which application threads were stopped: 0.0225920 seconds

4: a web server product sample and process

JAVA_OPTS=" -server -Xmx2g -Xms2g -Xmn256m -XX:PermSize=128m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 "

 

最初的時候我們用UseParallelGCUseParallelOldGCheap開了3GNewRatio設成1。這樣的配置下young gc發生頻率約123秒一次,平均每次花費80ms左右,full gc發生的頻率極低,每次消耗1s左右。從所有gc消耗系統時間看,系統使用率還是滿高的,但是不論是young gc還是old gcapplication thread pause的時間比較長,不合適 web 應用。我們也調小New Generation的,但是這樣會使full gc時間加長。

 

後來我們就用CMS gc-XX:+UseConcMarkSweepGC),當時的總heap還是3g,新生代1.5g後,觀察不是很理想,改爲jvm heap2g新生代設置-Xmn1g,在這樣的情況下young gc發生的頻率變成78秒一次,平均每次時間40-50毫秒左右,CMS gc很少發生,每次時間在init-markremarktwo steps stop all app thread)總共平均花費80-90ms左右。

 

在這裏我們曾經New Generation調大到1400m,總共2gjvm heap,平均每次ygc花費時間60-70ms左右,CMS gcinit-markremark之和平均在50ms左右,這裏我們意識到錯誤的方向,或者說CMS的作用,所以進行了修改。

 

最後我們調小New Generation256myoung gc 23秒發生一次,平均停頓時間在25毫秒左右,CMS gcinit-markremark之和平均在50ms左右,這樣使系統比較平滑,經壓力測試,這個配置下系統性能是比較高的。

 

在使用CMS gc的時候他有兩種觸發gc的方式:gc估算觸發和heap佔用觸發。我們的1.5.0.09 環境下有次old heap佔用在30%左右,她就頻繁gc,個人感覺系統估算觸發這種方式不靠譜,還是用 heap 使用比率觸發比較穩妥。

 

這些數據都來自64位測試機,過程中的數據都是我在jboss log找的,當時沒有記下來,可能存在一點點偏差,但不會很大,基本過程就是這樣。

5: 總結

web server作爲交互性要求較高的應用,我們應該使用Parallel+CMSUseParNewGC這個在jdk6 -server上是默認的new generation gc,新生代不能太大,這樣每次pause會短一些。CMS mark-sweep generation可以大一些,可以根據pause time實際情況控制。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章