這一篇對(duì)項(xiàng)目的優(yōu)化實(shí)戰(zhàn)酬荞,能讓你面試加分30%!

但如果你想了解Java大數(shù)據(jù)平臺(tái)開發(fā)瞧哟、項(xiàng)目系統(tǒng)的優(yōu)化實(shí)戰(zhàn)混巧。請(qǐng)繼續(xù)向下閱讀。

項(xiàng)目背景

該項(xiàng)目是銀行自用項(xiàng)目勤揩,是多租戶的數(shù)據(jù)查詢平臺(tái)咧党。可能很多人對(duì)這個(gè)概念不是很清楚陨亡,別急傍衡,容我做個(gè)簡(jiǎn)單的介紹深员,就明白這個(gè)系統(tǒng)是干嘛的了。

項(xiàng)目簡(jiǎn)介

首先蛙埂,整個(gè)系統(tǒng)是基于Dubbo的分布式系統(tǒng)架構(gòu)倦畅,數(shù)據(jù)存儲(chǔ)統(tǒng)一存儲(chǔ)在數(shù)據(jù)倉(cāng)庫(kù)。數(shù)據(jù)倉(cāng)庫(kù)提供多種存儲(chǔ)方式绣的,包括MySQL叠赐、HDFS、HBSE被辑、Hive燎悍、Impala、Spark盼理、ElasticSearch等等谈山。而如果讓業(yè)務(wù)方去做數(shù)據(jù)存取操作,顯然是非常麻煩的宏怔。所以在業(yè)務(wù)系統(tǒng)與數(shù)據(jù)倉(cāng)庫(kù)之間再搭建了一個(gè)數(shù)據(jù)查詢系統(tǒng)——這就是本篇文章的主角奏路。

系統(tǒng)架構(gòu)

image

項(xiàng)目源碼

這里會(huì)給大家展示項(xiàng)目的部分源碼,當(dāng)然臊诊,所展示的源碼都是功能性的而非項(xiàng)目業(yè)務(wù)相關(guān)(即任何項(xiàng)目都可以有這些代碼)鸽粉,大家可以先找找茬。


image
image
image
image

通過(guò)4張圖抓艳,大家應(yīng)該對(duì)該系統(tǒng)之前的編碼水平有了大致的了解触机。下面我將一一解鎖每張?jiān)创a圖的故事。

源碼1:

源碼1是我在做功能調(diào)試的時(shí)候發(fā)現(xiàn)的一個(gè)BUG玷或,邏輯非常簡(jiǎn)單儡首,就是比對(duì)兩個(gè)id是否相等。但為什么這就產(chǎn)生BUG了呢偏友?
很簡(jiǎn)單蔬胯,就是包裝類的緩存!
Integer和Long類型會(huì)有1個(gè)byte的緩存位他,即 -128 ~ 127氛濒,當(dāng)比較數(shù)的返回在此之間時(shí),因?yàn)槎际鞘褂玫木彺娑焖琛r?yàn)證代碼如下:

package demo;

public class IntegerCacheDemo {

    public static void main(String[] args) {
        compare(1,1);
        compare(127,127);
        compare(128,128);

        compareWithEquals(1,1);
        compareWithEquals(127,127);
        compareWithEquals(128,128);
    }

    /**
     * 錯(cuò)誤的包裝類比較
     * @param a
     * @param b
     */
    public static void compare(Integer a, Integer b){
        System.out.println(a == b ? a + " == " + b:a + " != " + b);
    }
    /**
     * 正確的的包裝類比較
     * @param a
     * @param b
     */
    public static void compareWithEquals(Integer a, Integer b){
        System.out.println(a.equals(b) ? a + " == " + b:a + " != " + b);
    }
}

測(cè)試結(jié)果:


image

測(cè)試的結(jié)果印證了前面的說(shuō)法舞竿。

眾所周知, == 比較是直接比較的地址窿冯,而由于緩存的原因骗奖,包裝類緩存所指向的都是同一個(gè)對(duì)象,所有 == 判斷返回true,而當(dāng)超出了緩存的返回重归,包裝類的對(duì)象都是新創(chuàng)建的地址,使用 == 判斷會(huì)返回false厦凤,而equals判斷使用的是重寫的equals方法鼻吮,Integer的equals方法如下:

    public boolean equals(Object obj) {
        //判斷類型是否相同
        if (obj instanceof Integer) {
            //如果相同則判斷值是否相同,this.value存儲(chǔ)的是int類型值较鼓, == 與   
            //Integer比較椎木,會(huì)觸發(fā)自動(dòng)拆箱, 即等價(jià)于  int == int 判斷
            return this.value == (Integer)obj;
        } else {
            return false;
        }
    }

再來(lái)看IntegerCache的源碼吧博烂。


image

注意看全紅部分香椎,相信大家都明白了吧。 其他的包裝類如Long禽篱、Short畜伐、Byte等都有對(duì)應(yīng)的緩存,而且都是一個(gè)byte的取值范圍躺率。

源碼2:

請(qǐng)注意玛界,源碼2是在上線第二天就引起了線上事故。
業(yè)務(wù)描述

業(yè)務(wù)方通過(guò)查詢接口調(diào)用查詢平臺(tái)悼吱,查詢平臺(tái)通過(guò)Zookepper訪問(wèn)到Hbase獲取數(shù)據(jù)并返回慎框。

問(wèn)題排查

通過(guò)錯(cuò)誤日志,可以查到當(dāng)時(shí)有很多請(qǐng)求查詢失敗后添,并且偶爾會(huì)有一個(gè)查詢成功笨枯,且失敗數(shù)量是成線性增長(zhǎng)的趨勢(shì)。當(dāng)時(shí)我就根據(jù)經(jīng)驗(yàn)判斷是連接出了問(wèn)題遇西。
果然馅精,通過(guò)查看zookeeper日志,發(fā)現(xiàn)確實(shí)報(bào)連接數(shù)超過(guò)最大限制努溃,但業(yè)務(wù)方反饋業(yè)務(wù)才上線硫嘶,使用人數(shù)也就10來(lái)人。那么可以判斷梧税,代碼存在BUG沦疾。

問(wèn)題解決

首先,修改代碼上線是需要經(jīng)過(guò)一個(gè)流程的第队,不適合短時(shí)間解決哮塞。 而我們zookepper的最大連接數(shù)配置的是100,我們先將最大連接數(shù)調(diào)整到600凳谦,然后查找代碼BUG修復(fù)忆畅。

通過(guò)走查代碼,發(fā)現(xiàn)代碼中有一個(gè)非常低級(jí)且致命的低級(jí)錯(cuò)誤(大家有沒(méi)有發(fā)現(xiàn)呢尸执?)家凯,就是圖2的try-cache中的代碼缓醋,調(diào)用了createConnection(conf)方法兩次,其中一個(gè)連接返回給調(diào)用者绊诲,而另外一個(gè)連接創(chuàng)建后則沒(méi)有返回送粱。返回的連接會(huì)在使用后正確關(guān)閉,而沒(méi)有返回的連接由于永遠(yuǎn)不可能會(huì)有調(diào)用者,也就不可能手動(dòng)釋放掂之,而只能等待超時(shí)自動(dòng)釋放抗俄,超時(shí)時(shí)間在代碼中也看到了-30000ms。這就解釋了為什么并發(fā)不高的情況下世舰,連接首先掛掉了动雹。去掉此段代碼即可。

4.優(yōu)化升級(jí)

請(qǐng)注意看上一段加粗的文字跟压,我為什么加粗呢胰蝠? 肯定是另有乾坤啊,哈哈哈哈~~~裆馒!
圖2中有3個(gè)代碼片段姊氓, 可以看到,整個(gè)操作流程是 : 獲取配置 -> 創(chuàng)建Util對(duì)象 -> 創(chuàng)建連接 -> 查詢 -> 關(guān)閉連接喷好。

OMG翔横!OMG!OMG梗搅! 不得不驚嘆在21世紀(jì)的20年代禾唁, 居然還能看到這樣的代碼。OK无切,兩個(gè)問(wèn)題荡短,其一,整個(gè)流程少了個(gè)連接池吧哆键? 其二掘托,util對(duì)象居然是要new出來(lái)使用。 不使用連接池的弊端無(wú)需多說(shuō)籍嘹,太浪費(fèi)資源了闪盔。我們可以看看在單機(jī)并發(fā)下TCP連接數(shù)。


image

看到那個(gè)頂上去的尖了嗎辱士。 并發(fā)也不是特別高泪掀, 20線程 * 200 次循環(huán)。 可以想象颂碘,如果在生產(chǎn)環(huán)境异赫,并發(fā)量如果稍微上去一點(diǎn),這機(jī)器是最先扛不住的。

ok塔拳,繼續(xù)整鼠证。優(yōu)化思路:

  1. 配置和工具類分離,創(chuàng)建配置對(duì)象靠抑,而不創(chuàng)建工具對(duì)象
  2. 使用連接池管理連接名惩,這一點(diǎn)比較好辦,Hbase的Java客戶端提供了連接池孕荠。

經(jīng)過(guò)優(yōu)化,TCP連接基本比較穩(wěn)定攻谁,優(yōu)化代碼我這里就不貼了稚伍,代碼還是不少,重要的是思路而不是代碼戚宦。

源碼3 + 源碼4:

源碼3比較簡(jiǎn)單个曙,就是最基本的JDBC獲取連接操作,同樣的問(wèn)題受楼,整個(gè)操作都是創(chuàng)建連接垦搬、查詢、關(guān)閉連接艳汽,而沒(méi)有使用到連接池猴贰。但這一點(diǎn)和Hbase操作又有所不同,Hbase的數(shù)據(jù)源在系統(tǒng)中只有一個(gè)河狐,而JDBC的數(shù)據(jù)源就非常多了米绕,包括MySQL、Hive馋艺、Impala都是使用JDBC來(lái)連接的栅干,而每一個(gè)數(shù)據(jù)庫(kù)就是一個(gè)數(shù)據(jù)源。這樣我們系統(tǒng)中就會(huì)有非常多的數(shù)據(jù)源捐祠,而不是單一的數(shù)據(jù)資源管理碱鳞。

而源碼4我認(rèn)為是比較好的代碼,通過(guò)令牌池的機(jī)制限制了單臺(tái)服務(wù)器的最大數(shù)據(jù)庫(kù)連接數(shù)量踱蛀,這種思想在高并發(fā)中也可以使用窿给。 相對(duì)于限流的一種機(jī)制,他最大限度的保證了服務(wù)器的穩(wěn)定性星岗,不像源碼2那樣直接導(dǎo)致服務(wù)不可用填大。

這里的優(yōu)化思路就是在一個(gè)數(shù)據(jù)源對(duì)應(yīng)一個(gè)連接池,而多個(gè)數(shù)據(jù)源則對(duì)應(yīng)多個(gè)連接池俏橘,然后對(duì)多個(gè)連接池進(jìn)行緩存允华,當(dāng)請(qǐng)求訪問(wèn)的時(shí)候,首先根據(jù)請(qǐng)求查找到對(duì)應(yīng)的連接池,然后再?gòu)倪B接池獲取一個(gè)連接返回靴寂。這樣就解決了頻繁創(chuàng)建連接的問(wèn)題磷蜀。這種方式暫時(shí)提升了系統(tǒng)的并發(fā)度,但這種方式對(duì)服務(wù)器的本地資源占用比較多百炬,還有其他的解決方案褐隆,比如開源的中間件MyCat等。

如果你看到了這里剖踊,證明你太有耐心了 哈哈~J!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末德澈,一起剝皮案震驚了整個(gè)濱河市歇攻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌梆造,老刑警劉巖缴守,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異镇辉,居然都是意外死亡屡穗,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門忽肛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)村砂,“玉大人,你說(shuō)我怎么就攤上這事屹逛」烤担” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵煎源,是天一觀的道長(zhǎng)色迂。 經(jīng)常有香客問(wèn)我,道長(zhǎng)手销,這世上最難降的妖魔是什么歇僧? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮锋拖,結(jié)果婚禮上诈悍,老公的妹妹穿的比我還像新娘。我一直安慰自己兽埃,他們只是感情好侥钳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著柄错,像睡著了一般舷夺。 火紅的嫁衣襯著肌膚如雪苦酱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天给猾,我揣著相機(jī)與錄音疫萤,去河邊找鬼。 笑死敢伸,一個(gè)胖子當(dāng)著我的面吹牛扯饶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播池颈,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼尾序,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了躯砰?” 一聲冷哼從身側(cè)響起蹲诀,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎弃揽,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體则北,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡矿微,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了尚揣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涌矢。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖快骗,靈堂內(nèi)的尸體忽然破棺而出娜庇,到底是詐尸還是另有隱情胜卤,我是刑警寧澤耕陷,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站温亲,受9級(jí)特大地震影響藕溅,放射性物質(zhì)發(fā)生泄漏匕得。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一巾表、第九天 我趴在偏房一處隱蔽的房頂上張望汁掠。 院中可真熱鬧,春花似錦集币、人聲如沸考阱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)乞榨。三九已至秽之,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間姜凄,已是汗流浹背政溃。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留态秧,地道東北人董虱。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像申鱼,于是被迫代替她去往敵國(guó)和親愤诱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354