性能優(yōu)化1:kryo序列化
定制序列化
- 自定義的bolt之間emit數(shù)據(jù)是實(shí)體類的時(shí)候,注冊(cè)kryo
- Storm 使用 Kryo 來處理序列化。如果要實(shí)現(xiàn)自定義的序列化生成器,需要注冊(cè)一個(gè)新的 Kryo 的序列化生成器。
可以通過拓?fù)涞?topology.kryo.register 屬性來添加自定義序列化生成器。兩種姿勢:
只有一個(gè)待注冊(cè)的類的名稱。在這種情況下,Storm 會(huì)使用 Kryo 的 FieldsSerializer 來序列化該類。conf.registerSerialization(UserEntity.class);
一個(gè)包含待注冊(cè)的類的名稱和對(duì)應(yīng)的序列化實(shí)現(xiàn)類名稱,該序列化實(shí)現(xiàn)類實(shí)現(xiàn)了 com.esotericsoftware.kryo.Serializer接口。
topology.kryo.register:
- com.ly.CustomType1
- com.ly.CustomType2: com.ly.serializer.CustomType2Serializer
- com.ly.CustomType3
Storm序列化文章:
https://www.cnblogs.com/intsmaze/p/7044042.html
http://storm.apache.org/releases/1.0.6/Serialization.html
性能優(yōu)化2:KafkaBolt批量提交
props.put("request.required.acks", "0");
props.put("producer.type", " async");
props.put("message.send.max.retries", "3");?props.put("batch.num.messages", "200");
props.put("send.buffer.bytes", "1024*100");
性能優(yōu)化3:使用組件的并行度代替線程池
Storm 自身是一個(gè)分布式、多線程的框架,對(duì)每個(gè)Spout 和Bolt,我們都可以設(shè)置其并發(fā)度;它也支持通過rebalance 命令來動(dòng)態(tài)調(diào)整并發(fā)度,把負(fù)載分?jǐn)偟蕉鄠€(gè)Worker 上。如果自己在組件內(nèi)部采用線程池做一些計(jì)算密集型的任務(wù),比如JSON 解析,有可能使得某些組件的資源消耗特別高,其他組件又很低,導(dǎo)致Worker 之間資源消耗不均衡,這種情況在組件并行度比較低的時(shí)候更明顯。
如某個(gè)Bolt 設(shè)置了1 個(gè)并行度,但在Bolt 中又啟動(dòng)了線程池,這樣導(dǎo)致的一種后果就是,集群中分配了這個(gè)Bolt 的Worker 進(jìn)程可能會(huì)把機(jī)器的資源都給消耗光了,影響到其他Topology 在這臺(tái)機(jī)器上的任務(wù)的運(yùn)行。如果真有計(jì)算密集型的任務(wù),我們可以把組件的并發(fā)度設(shè)大,Worker 的數(shù)量也相應(yīng)提高,讓計(jì)算分配到多個(gè)節(jié)點(diǎn)上。
性能優(yōu)化4:注意fieldsGrouping 的數(shù)據(jù)均衡性
fieldsGrouping 是根據(jù)一個(gè)或者多個(gè)Field 對(duì)數(shù)據(jù)進(jìn)行分組,不同的目標(biāo)Task 收到不同的數(shù)據(jù),而同一個(gè)Task 收到的數(shù)據(jù)會(huì)相同。
假設(shè)某個(gè)Bolt 根據(jù)用戶ID 對(duì)數(shù)據(jù)進(jìn)行fieldsGrouping,如果某一些用戶的數(shù)據(jù)特別多,而另外一些用戶的數(shù)據(jù)又比較少,那么就可能使得下一級(jí)處理Bolt 收到的數(shù)據(jù)不均衡,整個(gè)處理的性能就會(huì)受制于某些數(shù)據(jù)量大的節(jié)點(diǎn)。可以加入更多的分組條件或者更換分組策略,使得數(shù)據(jù)具有均衡性。
性能優(yōu)化5:優(yōu)先使用localOrShuffleGrouping
localOrShuffleGrouping 是指如果目標(biāo)Bolt 中的一個(gè)或者多個(gè)Task 和當(dāng)前產(chǎn)生數(shù)據(jù)的Task 在同一個(gè)Worker 進(jìn)程里面,那么就走內(nèi)部的線程間通信,將Tuple 直接發(fā)給在當(dāng)前Worker 進(jìn)程的目的Task。否則,同shuffleGrouping。localOrShuffleGrouping 的數(shù)據(jù)傳輸性能優(yōu)于shuffleGrouping,因?yàn)樵赪orker 內(nèi)部傳輸,只需要通過Disruptor 隊(duì)列就可以完成,沒有網(wǎng)絡(luò)開銷和序列化開銷。因此在數(shù)據(jù)處理的復(fù)雜度不高, 而網(wǎng)絡(luò)開銷和序列化開銷占主要地位的情況下,可以優(yōu)先使用localOrShuffleGrouping 來代替shuffleGrouping。
性能優(yōu)化6:設(shè)置合理的Worker 數(shù)
Worker 數(shù)越多,性能越好?先看一張Worker 數(shù)量和吞吐量對(duì)比的曲線
從圖可以看出,在12 個(gè)Worker 的情況下,吞吐量最大,整體性能最優(yōu)。這是由于一方面,每新增加一個(gè)Worker 進(jìn)程,都會(huì)將一些原本線程間的內(nèi)存通信變?yōu)檫M(jìn)程間的網(wǎng)絡(luò)通信,這些進(jìn)程間的網(wǎng)絡(luò)通信還需要進(jìn)行序列化與反序列化操作,這些降低了吞吐率。
另一方面,每新增加一個(gè)Worker 進(jìn)程,都會(huì)額外地增加多個(gè)線程(Netty 發(fā)送和接收線程、心跳線程、SystemBolt 線程以及其他系統(tǒng)組件對(duì)應(yīng)的線程等),這些線程切換消耗了不少CPU,sys 系統(tǒng)CPU 消耗占比增加,在CPU 總使用率受限的情況下,降低了業(yè)務(wù)線程的使用效率。