1瓤湘、前言
????????作為一個(gè)工作在中國(guó)的程序員备蚓,在項(xiàng)目開(kāi)發(fā)中經(jīng)常會(huì)打印中文,當(dāng)然在編程中運(yùn)用中文(日志等)不可避免的會(huì)碰到編碼問(wèn)題烁峭,剛開(kāi)始遇到編碼問(wèn)題時(shí)容客,我也是挺不樂(lè)意去研究的,后來(lái)靜下心慢慢的去研究發(fā)現(xiàn)约郁,其實(shí)并沒(méi)有那么的難缩挑。
????????關(guān)于這個(gè)主題,網(wǎng)上看到了都是一模一樣鬓梅,可參照性低供置,下面來(lái)詳細(xì)講講遇到問(wèn)題和解決辦法。
2绽快、問(wèn)題
????????現(xiàn)有兩套CDH5.7.2集群芥丧,spark1.6-cdh5.7.2(內(nèi)網(wǎng)和預(yù)發(fā)布)紧阔,在一個(gè)Spark項(xiàng)目中進(jìn)行了大量的中文日志打印,在win和內(nèi)網(wǎng)發(fā)布日志打印都正常续担,但是發(fā)布到預(yù)發(fā)布集群擅耽,stdout中中文就亂碼了。在Spark job UI上看到日志如圖:
? ? ? ? 由于在內(nèi)網(wǎng)和開(kāi)發(fā)集群上都沒(méi)有問(wèn)題物遇,并且預(yù)發(fā)布和內(nèi)網(wǎng)機(jī)器系統(tǒng)一樣乖仇,檢查系統(tǒng)的默認(rèn)編碼也是一致,如下圖:
? ? ? ? 所以認(rèn)為是不是Spark ui上的編碼存在問(wèn)題询兴,于是查看stdout所在executor機(jī)器的stdout文件的編碼这敬,如圖:
????????這就明白為啥會(huì)亂碼了,日志輸出的編碼格式就不對(duì)了蕉朵,不亂碼才怪呢崔涂!可是這個(gè)日志輸出格式在哪配置呢?
3始衅、問(wèn)題排查過(guò)程
????????要知道java程序或者其他程序?qū)懳募r(shí)冷蚂,會(huì)先將對(duì)象轉(zhuǎn)為byte,然后再寫(xiě)入磁盤(pán)汛闸,磁盤(pán)只能存儲(chǔ)二進(jìn)制文件蝙茶,所以查看String.getByte方法,發(fā)現(xiàn)編碼來(lái)自這段代碼:
? ? ? ? 這里有一個(gè)defaultCharset诸老,繼續(xù)更進(jìn):
?????????至此也就明白一個(gè)java程序的編碼設(shè)置位置隆夯,這里要謝謝這位博主的文章:http://blog.csdn.net/u010234516/article/details/52842170 ,他還有一篇解釋UTf-8與GBK互轉(zhuǎn)的文章别伏,想一解編碼疑惑的同學(xué)可以參考參考蹄衷。
? ? ? ? 這時(shí)需要先確認(rèn)啟動(dòng)的Spark程序運(yùn)用了什么編碼格式,這個(gè)在Spark Job UI上就可以一目了然厘肮,如下圖:
? ? ? ? 這也就是日志文件的編碼格式愧口,那么要怎么將編碼格式更改為UTF-8呢?在代碼里設(shè)置是不管用的类茂,想知道為啥耍属?點(diǎn)這里!
? ? ? ? 首先需要明確巩检,一個(gè)java厚骗、scala程序的發(fā)布包括編寫(xiě)、編譯和運(yùn)行兢哭,那么也就涉及三個(gè)過(guò)程的編碼格式领舰,我們來(lái)一個(gè)個(gè)的確認(rèn)。首先確認(rèn)編碼時(shí)采用的編碼格式為UTF-8,這個(gè)采用idea和eclipse編碼都可以非常簡(jiǎn)單的查看提揍,idea如下圖:
? ? ? ? 顯然代碼編寫(xiě)時(shí)的編碼沒(méi)有問(wèn)題,再看編譯時(shí)的編碼煮仇,我采用maven進(jìn)行打包編譯的劳跃,在pom.xml中有這么一行:
? ? ? ? 也就是說(shuō)編寫(xiě)、編譯的編碼格式都正常浙垫,那就是運(yùn)行時(shí)的編碼存在問(wèn)題刨仑,那就需要在啟動(dòng)java進(jìn)程時(shí),設(shè)置編碼格式夹姥,這里請(qǐng)參照Spark作業(yè)提交時(shí)的環(huán)境變量來(lái)源杉武,
? ? ? ? 最后再spark-submit的時(shí)候增加如下參數(shù)即可:參照Spark配置參數(shù)
--conf spark.driver.extraJavaOptions=" -Dfile.encoding=utf-8 " \
--conf spark.executor.extraJavaOptions=" -Dfile.encoding=utf-8 " \
那么spark默認(rèn)在哪獲取這個(gè)file.encoding呢?容我賣(mài)再研究下辙售,寫(xiě)到下一篇文章里轻抱。