由Elasticsearch的API命令,引发的金融业生产故障
作者介紹
李猛,數(shù)據(jù)領(lǐng)域?qū)<?#xff0c;Elastic Stack國(guó)內(nèi)頂尖實(shí)戰(zhàn)專(zhuān)家,國(guó)內(nèi)首批Elastic官方認(rèn)證工程師21人之一。2012年入手Elasticsearch,對(duì)Elastic Stack技術(shù)棧開(kāi)發(fā)、架構(gòu)、運(yùn)維、源碼、算法等方面有深入實(shí)戰(zhàn)經(jīng)驗(yàn)。負(fù)責(zé)過(guò)多種Elastic Stack項(xiàng)目,包括大數(shù)據(jù)分析領(lǐng)域、機(jī)器學(xué)習(xí)預(yù)測(cè)領(lǐng)域、業(yè)務(wù)查詢(xún)加速領(lǐng)域、日志分析領(lǐng)域、基礎(chǔ)指標(biāo)監(jiān)控領(lǐng)域等。十余年技術(shù)實(shí)戰(zhàn)從業(yè)經(jīng)驗(yàn),擅長(zhǎng)大數(shù)據(jù)多種技術(shù)棧混合,系統(tǒng)架構(gòu)領(lǐng)域。
序言
圖示:Elasticsearch目前在DB-Engine綜合排名第8
Elasticsearch博大精深,提供了非常豐富的應(yīng)用場(chǎng)景功能,也提供了豐富的API命令操作,有些API非常好用,有的API用一用就要出大事,防不勝防。
以下圍繞某客戶(hù)一次客戶(hù)端應(yīng)用程序錯(cuò)用Cluster State命令展開(kāi),從問(wèn)題定位到問(wèn)題解決,記錄自己的過(guò)程與方法,還有一些心得總結(jié)(注:具體客戶(hù)信息不便透漏,以下部分圖片信息僅為示意圖)。
一、案例介紹
1、項(xiàng)目背景概要介紹
客戶(hù)用ES來(lái)解決日常的數(shù)據(jù)查詢(xún)與存儲(chǔ),利用ES非常好的橫向擴(kuò)展特性,滿(mǎn)足多種場(chǎng)景應(yīng)用。
ES集群版本屬于5.6.x,已經(jīng)超出Elastic官方支持的版本,集群節(jié)點(diǎn)數(shù)不到10個(gè),節(jié)點(diǎn)硬件配置屬于均衡一致性,標(biāo)準(zhǔn)的性能型合理范圍硬件配置,應(yīng)用于業(yè)務(wù)系統(tǒng)提供查詢(xún)或者更新等,日常都有提供定期巡檢,基本正常穩(wěn)定,不過(guò)一直側(cè)重的是集群運(yùn)維本身,很少會(huì)深入到應(yīng)用端程序去巡檢分析,業(yè)務(wù)線(xiàn)太多,經(jīng)費(fèi)有限。
ES集群設(shè)置并未采用Master與Data分離設(shè)計(jì),所有節(jié)點(diǎn)均是同等角色權(quán)限。ES集群數(shù)據(jù)量也是屬于正常支撐能力范圍,集群索引的分片數(shù)量在2w以上,注意這個(gè)數(shù)字,后面會(huì)基于此來(lái)突破尋找問(wèn)題。
客戶(hù)端應(yīng)用程序基于Spring data elasticsearch開(kāi)發(fā)框架,引用Trasnport-client直連模式,中間未采用任何代理Proxy負(fù)載產(chǎn)品。
客戶(hù)端應(yīng)用程序部署了多個(gè)實(shí)例,按照2的倍數(shù)增加,需要做一些“大量”數(shù)據(jù)的寫(xiě)入與查詢(xún),瞬間并發(fā)的操作ES集群,無(wú)論怎么操作,ES的并發(fā)數(shù)并不高,但應(yīng)用端程序就是運(yùn)行不快,這很不合常理也不合事宜,常識(shí)告訴我這不正常。
圖示:客戶(hù)公司的應(yīng)用項(xiàng)目架構(gòu)示意圖,客戶(hù)端采用Transport-client直連模式
2、問(wèn)題現(xiàn)象與事故原因
客戶(hù)端應(yīng)用程序只要開(kāi)始運(yùn)行,ES集群立刻會(huì)慢起來(lái),但查看ES集群整體資源消耗,ES所在節(jié)點(diǎn)CPU/MEM/硬盤(pán)IO并不高,其數(shù)據(jù)節(jié)點(diǎn)甚至非常低,遠(yuǎn)遠(yuǎn)沒(méi)有達(dá)到節(jié)點(diǎn)的瓶頸。
經(jīng)過(guò)細(xì)細(xì)觀察發(fā)現(xiàn),集群的Master節(jié)點(diǎn)流量特別高,其余節(jié)點(diǎn)數(shù)據(jù)流量都傳給Master節(jié)點(diǎn),超出了Master單節(jié)點(diǎn)網(wǎng)絡(luò)IO的極限,這顯然不正常。但在生產(chǎn)環(huán)境上并不容易排查。后面經(jīng)過(guò)在本地開(kāi)發(fā)環(huán)境模擬壓測(cè),終于確定了問(wèn)題來(lái)源,是客戶(hù)端的某個(gè)集群管理操作 API引起的。
最終,找到了 Cluster State Api 統(tǒng)計(jì)命令引起的,客戶(hù)端應(yīng)用程序每次做實(shí)際業(yè)務(wù)前,都會(huì)調(diào)用這個(gè)API命令獲取集群一些索引與Mapping信息,由于客戶(hù)端是采用多線(xiàn)程設(shè)計(jì),且部署多個(gè)實(shí)例,只要并發(fā)數(shù)高,所有流量必然打到Master節(jié)點(diǎn),造成整個(gè)集群響應(yīng)慢。由于整個(gè)集群有近2w個(gè)分片,執(zhí)行一次State 命令,需要統(tǒng)計(jì)匯總集群所有索引分片信息,并最終匯總到Master節(jié)點(diǎn),造成實(shí)際Master節(jié)點(diǎn)網(wǎng)絡(luò)IO超過(guò)極限。
圖示:cluster state api返回內(nèi)容,索引越多,返回內(nèi)容越大。
二、排查過(guò)程&分析手段
以上我們快速講了一下問(wèn)題現(xiàn)象與事故原因, 下面重點(diǎn)聊一下問(wèn)題排查過(guò)程以及采用的工具方法思維等。
特別說(shuō)明,由于是遠(yuǎn)程協(xié)作分析排查以及客戶(hù)公司的行業(yè)特性,外部不能直接操作遠(yuǎn)程任何節(jié)點(diǎn),必須通過(guò)客戶(hù)公司運(yùn)維人員間接指導(dǎo)操作排查,過(guò)程稍微有點(diǎn)曲折。
1、服務(wù)端集群排查
首先是ES集群?jiǎn)栴}排查,這是很正常直接的思維,在問(wèn)題爆發(fā)點(diǎn)排查(ps:類(lèi)似警察先趕到案發(fā)現(xiàn)場(chǎng),采集證據(jù))。由于集群版本是5.6.x,一些原因并未啟用官方的XPack功能,所以也就沒(méi)有自帶的Kibana監(jiān)控可視化報(bào)表,國(guó)內(nèi)早期多數(shù)用戶(hù)都是采用開(kāi)源免費(fèi)版本搭建集群,客戶(hù)公司基于Zabbix搭建有集群節(jié)點(diǎn)的基礎(chǔ)指標(biāo)監(jiān)控,總算是有一個(gè),非常難得。
1)zabbix監(jiān)控分析
很快基于Zabbix展開(kāi)各個(gè)ES機(jī)器節(jié)點(diǎn)指標(biāo)監(jiān)控分析,按照常規(guī)套路,分析了CPU、內(nèi)存、磁盤(pán)IO等一切正常,并不高。這就非常令人困惑,明明集群響應(yīng)很慢,客戶(hù)端應(yīng)用程序開(kāi)發(fā)人員也如實(shí)反應(yīng),部署的實(shí)例非常少,所以初次分析下來(lái),并未發(fā)現(xiàn)明顯定位到問(wèn)題。
接著分析節(jié)點(diǎn)網(wǎng)絡(luò)IO,貌似發(fā)現(xiàn)了問(wèn)題點(diǎn),其中Master節(jié)點(diǎn)流量特別高,超出了網(wǎng)卡的極限;按照此套路,繼續(xù)查看了其它數(shù)據(jù)節(jié)點(diǎn)網(wǎng)絡(luò)IO,也比較高,然后觀察發(fā)現(xiàn),數(shù)據(jù)節(jié)點(diǎn)的網(wǎng)絡(luò)IO流量累計(jì)起來(lái)剛好等于Master節(jié)點(diǎn)網(wǎng)絡(luò)IO流量,終于算是找到了一個(gè)突破口。
注意,基于Zabbix雖然能監(jiān)控各個(gè)獨(dú)立節(jié)點(diǎn)的網(wǎng)絡(luò)流量,但并不能看到節(jié)點(diǎn)之間網(wǎng)絡(luò)流量,以及應(yīng)用客戶(hù)端與服務(wù)端之間,這很不友好,若有一張全網(wǎng)絡(luò)流量圖,將會(huì)更容易定位分析問(wèn)題。
圖示:Zabbix 網(wǎng)絡(luò)流量示意圖,僅僅能快速查看單獨(dú)節(jié)點(diǎn)
2)iftop監(jiān)控分析
借助Zabbix算是找到了突破口,接下來(lái)就需要一張網(wǎng)絡(luò)流量關(guān)聯(lián)圖。此時(shí)第一個(gè)想到的是 Elastic Stack Packetbeat 網(wǎng)絡(luò)IO流量包可視化監(jiān)控監(jiān)控,瞬間與客戶(hù)公司討論,能否安裝配置,顯然這個(gè)過(guò)程太慢,需要申請(qǐng)更多資源等麻煩,時(shí)間預(yù)計(jì)來(lái)不及。后面客戶(hù)公司運(yùn)維工程師臨時(shí)安裝 Linux 絡(luò)指令iftop,終于能夠分析ES所有節(jié)點(diǎn)網(wǎng)絡(luò)IO流量的流進(jìn)流出方向,但是觀察分析相對(duì)來(lái)說(shuō)比較痛苦,而且并不能繪制一個(gè)網(wǎng)絡(luò)圖譜,所以觀察起來(lái)還是不夠全面。
iftop僅僅在單機(jī)節(jié)點(diǎn)執(zhí)行,所以只能看到單個(gè)節(jié)點(diǎn)的網(wǎng)絡(luò)流量進(jìn)與出,不過(guò)這已經(jīng)非常好了,只是時(shí)間長(zhǎng)一點(diǎn)。
基于網(wǎng)絡(luò)IO流量進(jìn)出初步分析觀察,很快做出了決策,先是重啟了現(xiàn)有Master節(jié)點(diǎn),讓ES集群重新選舉新的Master,結(jié)果發(fā)現(xiàn)依然新選舉的Master節(jié)點(diǎn)流量依然巨大;接著也臨時(shí)申請(qǐng)?jiān)黾?個(gè)新的ES節(jié)點(diǎn),以為可以分散客戶(hù)端訪(fǎng)問(wèn)的壓力,事實(shí)上并未從根本上排查解決。此時(shí)的判斷是認(rèn)為某些業(yè)務(wù)索引查詢(xún),造成流量比較大,剛好在Master節(jié)點(diǎn)中轉(zhuǎn)匯總,這里其實(shí)還沒(méi)有分析到客戶(hù)端的流量,所以做了一些無(wú)用的緊急服務(wù)端調(diào)整,但也證明了問(wèn)題不在ES服務(wù)端。
圖示:iftop網(wǎng)絡(luò)流量示意圖,能分析到單節(jié)點(diǎn)的流量進(jìn)出,也是不錯(cuò)了
3)packetbeat監(jiān)控分析
由于一些原因,并未部署Elastic Stack 監(jiān)控分析產(chǎn)品,特別推薦Packetbeat網(wǎng)絡(luò)流量監(jiān)控分析產(chǎn)品,官方默認(rèn)提供的網(wǎng)絡(luò)流量圖,非常有用,可以更快速定位流量走向,相比ittop,更加全面一些,可以總結(jié)為iftop的網(wǎng)絡(luò)版本。Packetbeat內(nèi)置官方一些可視化報(bào)表,如果覺(jué)得不夠,可以基于ES提供的分析能力自行設(shè)計(jì)。
圖示: packetbeta網(wǎng)絡(luò)IO流量監(jiān)控分析圖,輸入與輸出
2、客戶(hù)端排查
其次是從客戶(hù)端應(yīng)用排查。但實(shí)際上,客戶(hù)公司運(yùn)維人員第一時(shí)間發(fā)現(xiàn)問(wèn)題,聯(lián)系到我,我的第一個(gè)問(wèn)題就是客戶(hù)端應(yīng)用在做什么業(yè)務(wù),業(yè)務(wù)類(lèi)型是什么。運(yùn)維人員也如實(shí)告知正在做的業(yè)務(wù)類(lèi)型以及應(yīng)用情況,其實(shí)只能概要說(shuō)明一下,詳細(xì)的業(yè)務(wù)操作流程與影響的是不知道的,對(duì)于我來(lái)說(shuō),反正就知道了有個(gè)業(yè)務(wù)操作在影響著集群,具體怎么影響,還得繼續(xù)排查。必須說(shuō)明一下,這個(gè)可能是國(guó)內(nèi)IT運(yùn)維界的通病,看起來(lái)運(yùn)維屬于末端支持,本質(zhì)更應(yīng)該參與到業(yè)務(wù)系統(tǒng)的前沿陣地,從業(yè)務(wù)開(kāi)始了解背后的運(yùn)維問(wèn)題。
然后通過(guò)ES服務(wù)端排查,掌握了一些信息,但遠(yuǎn)遠(yuǎn)不足以定位到問(wèn)題,客戶(hù)端排查就任重道遠(yuǎn),必須要找出問(wèn)題所在。ES集群響應(yīng)慢有很多,但服務(wù)端只能發(fā)現(xiàn)問(wèn)題,并不能從根本上解決,于是通過(guò)在服務(wù)端運(yùn)行 thread_pool 與 task 命令,發(fā)現(xiàn)了集群的管理線(xiàn)程池特別多,任務(wù)一直爆滿(mǎn),這不正常,這就更加肯定一定是客戶(hù)端的某些應(yīng)用在惡意操作這些命令。
1)thread_pool 監(jiān)控分析
集群響應(yīng)慢,集群線(xiàn)程池是一個(gè)必須考慮的點(diǎn),其中會(huì)查看到累計(jì)的任務(wù)量,經(jīng)過(guò)打開(kāi)指令觀察,其中的 management 線(xiàn)程池特別高,由此判斷客戶(hù)端正在做一些任務(wù),且屬于management 線(xiàn)程池的,目前具體的依然不能確定,因?yàn)闆](méi)有看到客戶(hù)端應(yīng)用具體的代碼調(diào)用方式。
圖示:thread_pool示意圖,可以監(jiān)控ES節(jié)點(diǎn)任務(wù)數(shù)
2)task監(jiān)控分析
借助thread_pool分析,可以定位到 management 線(xiàn)程池正在大規(guī)模做任務(wù),同理借助task 查看分析 具體做的任務(wù)是什么。(ps:實(shí)際客戶(hù)環(huán)境中,發(fā)現(xiàn)是大量的state、stats任務(wù),其中state任務(wù)數(shù)明顯要高,且非常不正常,這里不方便透漏,后面會(huì)詳細(xì)列出如何壓測(cè)出來(lái)此結(jié)果)
圖示:task示意圖,可以查看到具體的任務(wù)類(lèi)型
3)stats監(jiān)控分析
借助 task 監(jiān)控分析,發(fā)現(xiàn)有大量的stats指令,接著在服務(wù)端執(zhí)行一次,看看情況如何,實(shí)際發(fā)現(xiàn)響應(yīng)也比較慢,但按理是正常的,產(chǎn)生的隊(duì)列次數(shù)并不高,只是執(zhí)行慢,基于以上判斷應(yīng)該是別的任務(wù)阻塞導(dǎo)致。
stats 負(fù)責(zé)集群監(jiān)控檢查響應(yīng),常規(guī)的集群yellow,red,green就來(lái)自與此;另外也收集索引的統(tǒng)計(jì)信息,節(jié)點(diǎn)的統(tǒng)計(jì)信息,返回的數(shù)據(jù)量不多,常規(guī)下可以忽略不記,不過(guò)注意后面transport-client 訪(fǎng)問(wèn)需要。
圖示:stats命令執(zhí)行示意圖
4)state監(jiān)控分析
借助 task 監(jiān)控分析,發(fā)現(xiàn)有大量的state指令,接著在服務(wù)端執(zhí)行一次,發(fā)現(xiàn)了問(wèn)題點(diǎn),執(zhí)行一次時(shí)間很長(zhǎng),且響應(yīng)返回的內(nèi)容超過(guò)70mb,這是問(wèn)題,可以回答為什么之前的master節(jié)點(diǎn)流量如此之高。終于問(wèn)題越來(lái)越清晰了,也越來(lái)越確定了。
圖示:state命令執(zhí)行示意圖
5)transport-client應(yīng)用訪(fǎng)問(wèn)
借助前面服務(wù)端現(xiàn)象分析,越來(lái)越確定問(wèn)題出在客戶(hù)端應(yīng)用代碼,大概率是操作不正確。
首先與客戶(hù)交流,詢(xún)問(wèn)客戶(hù)端應(yīng)用代碼訪(fǎng)問(wèn)ES的方式與程序版本,客戶(hù)端開(kāi)發(fā)團(tuán)隊(duì)很好配合,很快了解到應(yīng)用客戶(hù)端基于spring data elasticsearch框架,采用transport-client機(jī)制訪(fǎng)問(wèn)操作ES,但此時(shí)是不能定位是客戶(hù)端造成的,也不能匆忙要求客戶(hù)端提供源碼。接下來(lái)很快在本地編寫(xiě)相應(yīng)的測(cè)試程序源碼。
Transport-client客戶(hù)端綁定代碼
/*模擬spring data elasticsearch配置transport-client,示例來(lái)自官方文檔*/ @Configuration public class TransportClientConfig extends ElasticsearchConfigurationSupport {@Beanpublic Client elasticsearchClient() throws UnknownHostException {Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build(); TransportClient client = new PreBuiltTransportClient(settings);client.addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300)); return client;}@Bean(name = { "elasticsearchOperations", "elasticsearchTemplate" })public ElasticsearchTemplate elasticsearchTemplate() throws UnknownHostException {ElasticsearchTemplate template = new ElasticsearchTemplate(elasticsearchClient, elasticsearchConverter);template.setRefreshPolicy(refreshPolicy()); return template;} }6)jmeter壓測(cè)模擬
因?yàn)槟承┰?#xff0c;我們只能提供間接性的服務(wù)方式,所以為了徹底解決上面的問(wèn)題,需要在本地模擬測(cè)試,必須要模擬出生產(chǎn)的問(wèn)題,才能要求客戶(hù)端給出到源碼。基于前面服務(wù)端與客戶(hù)端應(yīng)用了解到的信息,接下來(lái)就是要做壓測(cè),特別選擇了jmeter工具,很快配置好本地集群,附加客戶(hù)端應(yīng)用訪(fǎng)問(wèn)代碼。壓測(cè)進(jìn)行時(shí),同步觀察ES服務(wù)端threadpool與task,能夠復(fù)現(xiàn)生產(chǎn)的問(wèn)題,很快就得到了想要的結(jié)果。
圖示:jmeter壓測(cè)示例,開(kāi)啟更多線(xiàn)程數(shù),超過(guò)ES測(cè)試服務(wù)器線(xiàn)程數(shù)
圖示:jmeter壓測(cè)示例,一次state命令執(zhí)行需要消耗非常多的資源
既然在本地環(huán)境,借助jmeter壓測(cè)出來(lái)生產(chǎn)上同樣的問(wèn)題,那么最后一步就是與客戶(hù)應(yīng)用開(kāi)發(fā)團(tuán)隊(duì)一起review代碼,這一步非常快,很快就定位到 客戶(hù)應(yīng)用端代碼在具體業(yè)務(wù)操作前,會(huì)調(diào)用Cluster State API,進(jìn)行業(yè)務(wù)邏輯判斷,判斷索引是否存在,判斷索引字段是否存在等。
最終問(wèn)題定位到了,產(chǎn)生原因也知道了,事情也算告一段落。
/* 客戶(hù)應(yīng)用端的某個(gè)訪(fǎng)問(wèn)代碼借助state來(lái)判斷索引的mapping信息 */public Map<String, Object> getMappingByField(String indexName, String type) throws IOException {ImmutableOpenMap<String, MappingMetaData> mappings = getClient().admin().cluster().prepareState().execute().actionGet().getState().getMetaData().getIndices().get(indexName).getMappings();if(mappings.isEmpty()) {return null;}Map<String, Object> mapping = mappings.get(type).getSourceAsMap();Map<String, Object> properties = (Map<String, Object>) mapping.get(ES_PROPERTIES);return properties;}3、問(wèn)題分析過(guò)程回顧
服務(wù)端分析,尋找突破口
客戶(hù)端分析,縮小排查范圍
模擬測(cè)試,復(fù)現(xiàn)生產(chǎn)問(wèn)題,確定問(wèn)題產(chǎn)生原因
應(yīng)用端代碼分析,找出問(wèn)題代碼
修改觀察,確認(rèn)問(wèn)題已經(jīng)解決
經(jīng)驗(yàn)總結(jié),復(fù)查所有其它相關(guān)代碼
圖示:問(wèn)題排查過(guò)程與流程
三、ES技術(shù)架構(gòu)原理
本次ES問(wèn)題排查涉及到的知識(shí)點(diǎn)以及技術(shù)性原理特別多,這里也來(lái)特別說(shuō)明一下與此關(guān)聯(lián)的架構(gòu)原理,供大家日后參考與分析。
1、ES架構(gòu)原理
ES對(duì)外雖然宣稱(chēng)是個(gè)分布式架構(gòu),可以橫向擴(kuò)展,但那說(shuō)的是數(shù)據(jù)節(jié)點(diǎn)或者其它非管理節(jié)點(diǎn)。實(shí)際上ES是典型主從架構(gòu)模式,一個(gè)集群只有一個(gè)Active Master節(jié)點(diǎn),Master節(jié)點(diǎn)負(fù)責(zé)管理集群所有元數(shù)據(jù)信息,其中包括節(jié)點(diǎn)信息、索引信息、分片信息、節(jié)點(diǎn)與索引路由信息、節(jié)點(diǎn)與分片路由信息等,集群執(zhí)行一次管理型的命令都需要先在Master執(zhí)行,然后分發(fā)到其它節(jié)點(diǎn)等。
了解這一點(diǎn)非常重要,可以很好的解釋,為什么在本次ES故障中,Master的網(wǎng)絡(luò)流量剛好等于其余節(jié)點(diǎn)網(wǎng)絡(luò)流量之和。客戶(hù)端應(yīng)用發(fā)起一次State統(tǒng)計(jì),首先都是Master節(jié)點(diǎn)接受指令,接著分發(fā)給其它節(jié)點(diǎn)執(zhí)行State統(tǒng)計(jì),最終匯總到Master節(jié)點(diǎn),造成了Master節(jié)點(diǎn)網(wǎng)絡(luò)流量奇高,超過(guò)網(wǎng)卡極限,ES集群響應(yīng)慢,但實(shí)際CPU與內(nèi)存消耗又不高。
聯(lián)想到這里,集群架構(gòu)是不是可以想象型的大膽設(shè)計(jì)一下,現(xiàn)在的ES集群只有一個(gè)大當(dāng)家,隨著集群規(guī)模越來(lái)越大,大當(dāng)家壓力越來(lái)越大,大當(dāng)家如果出現(xiàn)故障,就重新選大當(dāng)家,這聽(tīng)起來(lái)好像不符合社會(huì)組織學(xué)。那能否下次修改一下,設(shè)計(jì)一個(gè)有大當(dāng)家與二當(dāng)家的模式,大當(dāng)家與二大家職責(zé)再分離一下,大當(dāng)家太忙,二當(dāng)家分擔(dān)一些。
圖示:ES主從架構(gòu)分布式示意圖,一個(gè)集群只有一個(gè)Active Master節(jié)點(diǎn)
2、ES線(xiàn)程池
ES是個(gè)數(shù)據(jù)庫(kù)產(chǎn)品,內(nèi)部設(shè)計(jì)了多個(gè)任務(wù)線(xiàn)程池,不同的線(xiàn)程池任務(wù)與職責(zé)不一;線(xiàn)程池也分為多種類(lèi)型,不同的線(xiàn)程池類(lèi)型應(yīng)對(duì)任務(wù)場(chǎng)景不一樣;ES不同版本,線(xiàn)程池?cái)?shù)量與類(lèi)型會(huì)有大的差異,尤其是5.x與7.x版本,這種跨大版本,差異相當(dāng)大。
由于在某機(jī)構(gòu)做ES老師,時(shí)常與Java學(xué)員交流,發(fā)現(xiàn)了一些嚴(yán)重的認(rèn)知誤區(qū):1.很多學(xué)員認(rèn)為Java不能開(kāi)發(fā)數(shù)據(jù)庫(kù)產(chǎn)品,因?yàn)镚C機(jī)制;2.多數(shù)人學(xué)習(xí)掌握的Java線(xiàn)程池都只用來(lái)做簡(jiǎn)單的多線(xiàn)程業(yè)務(wù)場(chǎng)景,從未想象過(guò),類(lèi)似ES這樣集成了幾十個(gè)線(xiàn)程池的玩法。所以必須承認(rèn),ES是一個(gè)非常好的Java開(kāi)發(fā)高手學(xué)習(xí)參考的產(chǎn)品,特別是做后端開(kāi)發(fā),想要更加深入進(jìn)階的同學(xué)。
了解ES線(xiàn)程池內(nèi)部設(shè)計(jì)非常重要,可以很好的解釋,為什么本次ES故障中,只有Active Master節(jié)點(diǎn)的 management 線(xiàn)程池特別繁忙,其余線(xiàn)程池總體很閑,其余節(jié)點(diǎn)的線(xiàn)程池也非常閑。客戶(hù)端應(yīng)用發(fā)起一次State統(tǒng)計(jì),首先接收任務(wù)的是Master節(jié)點(diǎn)的management線(xiàn)程池,此線(xiàn)程池類(lèi)型為 scaling,且最大的線(xiàn)程數(shù)是一個(gè)固定值,不超過(guò)實(shí)際CPU合數(shù),也不能超過(guò)固定值5,而不是根據(jù)節(jié)點(diǎn)CPU核數(shù)來(lái)自動(dòng)彈性設(shè)計(jì)的。
當(dāng)客戶(hù)端應(yīng)用采用多線(xiàn)程執(zhí)行模式,且每次執(zhí)行業(yè)務(wù)操作前,都先執(zhí)行一次State 統(tǒng)計(jì)做業(yè)務(wù)邏輯判斷,這就無(wú)形中增加了集群的負(fù)載,增加了Master節(jié)點(diǎn)的任務(wù)數(shù)量,客戶(hù)端應(yīng)用實(shí)例數(shù)量越多,并發(fā)線(xiàn)程數(shù)也越多,集群Master節(jié)點(diǎn)就幾乎無(wú)法消化,畢竟Master節(jié)點(diǎn)就一個(gè);也正是由于負(fù)責(zé)執(zhí)行State任務(wù)的線(xiàn)程池是個(gè)固定值,Master節(jié)點(diǎn)CPU也不會(huì)打滿(mǎn),這就阻塞了所有的業(yè)務(wù)操作。
有時(shí)候官方文檔并沒(méi)有列出來(lái),需要通過(guò)ES源碼去查看,這點(diǎn)我至今也沒(méi)有想明白,不光是過(guò)去歷史版本,包括當(dāng)前最新版本也是一樣的,如當(dāng)前 7.15.x,有的線(xiàn)程池就沒(méi)有在官方文檔列出來(lái),但能在集群監(jiān)控中查看到。
圖示:ES內(nèi)部線(xiàn)程池劃分,(版本7.13.x,來(lái)自某機(jī)構(gòu)ESVIP課程)
3、ES集群統(tǒng)計(jì)執(zhí)行過(guò)程
Cluster State Api 執(zhí)行一次指令,指令會(huì)傳輸給Active Master節(jié)點(diǎn),Active Master分發(fā)指令給各個(gè)節(jié)點(diǎn),各個(gè)節(jié)點(diǎn)收集好信息之后回傳給Master,然后由 Master響應(yīng)給客戶(hù)端。
在開(kāi)始排查問(wèn)題中,初次判斷失誤,以為是客戶(hù)端在做大量的業(yè)務(wù)數(shù)據(jù)查詢(xún)?nèi)蝿?wù),所有節(jié)點(diǎn)數(shù)據(jù)量都很高,其中大量依賴(lài)Master節(jié)點(diǎn)對(duì)外輸出,實(shí)際不是。
圖示:Cluster State Api執(zhí)行過(guò)程示意圖
4、ES動(dòng)態(tài)創(chuàng)建索引
ES是典型的Free Schema數(shù)據(jù)產(chǎn)品,索引是可以動(dòng)態(tài)創(chuàng)建的,索引的字段也是可以動(dòng)態(tài)創(chuàng)建的,無(wú)需優(yōu)先聲明,更無(wú)需在應(yīng)用代碼中邏輯判斷是否存在,是否需要?jiǎng)?chuàng)建,這是ES非常好的動(dòng)態(tài)擴(kuò)展能力之一,基于此給應(yīng)用開(kāi)發(fā)帶來(lái)了相當(dāng)多的便利,比如著名的“大寬表模式”查詢(xún)場(chǎng)景,解決了海量數(shù)據(jù)關(guān)聯(lián)實(shí)時(shí)查詢(xún)的問(wèn)題。
ES可以提前創(chuàng)建索引,也可以不創(chuàng)建,寫(xiě)入第一條數(shù)據(jù),即可動(dòng)態(tài)創(chuàng)建索引,并同時(shí)創(chuàng)建索引自動(dòng)的mapping索引內(nèi)部結(jié)構(gòu)。若第二條數(shù)據(jù)寫(xiě)入,增加了很多新的數(shù)據(jù)內(nèi)容結(jié)構(gòu),則會(huì)自動(dòng)更新當(dāng)前索引的mapping,自動(dòng)刷新mapping。若新增加的數(shù)據(jù)字段缺失,也不會(huì)出錯(cuò)。ES默認(rèn)內(nèi)部會(huì)根據(jù)字段進(jìn)行推測(cè)其字段對(duì)應(yīng)的類(lèi)型。
#動(dòng)態(tài)創(chuàng)建空索引 PUT my-index-000001 { } #新增數(shù)據(jù),動(dòng)態(tài)創(chuàng)建索引,自動(dòng)推測(cè)字段類(lèi)型 PUT my-index-000001/_doc/1 {"create_date": "2015/09/02" } #更新數(shù)據(jù),動(dòng)態(tài)增加新字段類(lèi)型 PUT my-index-000001/_doc/1 {"my_float": "1.0", "my_integer": "1" ,"create_date": "2015/09/02" }5、transport-client
Transport client 是官方早期推出的應(yīng)用接入訪(fǎng)問(wèn)機(jī)制,自Rest Api 推出之后,官方就竭力要求切換過(guò)來(lái),其中緣由部分并沒(méi)有特別說(shuō)明。Transport是一種直連方式,直接連接到ES集群中,連接之后保持長(zhǎng)連接,并且需要定時(shí)執(zhí)行內(nèi)部的一些stats命令,來(lái)檢查集群監(jiān)控狀況,這個(gè)其實(shí)非常多余,在極端情況下也非常消耗集群資源。
ES集群內(nèi)部通信或者執(zhí)行其它指令,都是通過(guò)transport機(jī)制,即使是rest api執(zhí)行,內(nèi)部也是轉(zhuǎn)換為transport機(jī)制來(lái)執(zhí)行。
Rest 接入相比 Transport 更加解耦,也可以盡力避免惡意干擾 transport 通信,更多的此處不展開(kāi),后續(xù)會(huì)有另外的文章來(lái)寫(xiě)。
圖示:transport-client與rest api連接示意圖
四、專(zhuān)家建議
此次從問(wèn)題發(fā)現(xiàn)、問(wèn)題定位、問(wèn)題解決,花費(fèi)了幾天時(shí)間,有一些經(jīng)驗(yàn)建議有必要特別說(shuō)明一下。
1、全面的監(jiān)控體系
監(jiān)控體系是運(yùn)維的眼睛,集群的各種運(yùn)行信息,都需要借助強(qiáng)大的監(jiān)控體系來(lái)保障,提供實(shí)時(shí)的分析等。本次案例中,客戶(hù)公司監(jiān)控體系相對(duì)來(lái)說(shuō)比較傳統(tǒng)落后,雖然有zabbix,但在一些新的分析問(wèn)題方式上表現(xiàn)并不行,而且非常欠缺,如分析集群各個(gè)節(jié)點(diǎn)網(wǎng)絡(luò)流量進(jìn)出走向,包括服務(wù)端與客戶(hù)端的關(guān)系,都是沒(méi)有的。
選擇一款全面性且非常有獨(dú)立視角的監(jiān)控產(chǎn)品非常重要,Elastic Stack 是新時(shí)代的產(chǎn)物,新事物可以幫助我們提升優(yōu)化問(wèn)題排查思維。
2、權(quán)限安全隔離
絕大多數(shù)數(shù)據(jù)庫(kù)產(chǎn)品都提供了一些基本的安全策略與防護(hù),可以通過(guò)設(shè)置一些安全用戶(hù)群組與角色權(quán)限來(lái)限制避免此種問(wèn)題。
比如傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)MySQL,可以通過(guò)給客戶(hù)端應(yīng)用分配更小的權(quán)限來(lái)限制。早期ES版本由于ES并未提供安全防護(hù)機(jī)制,很多應(yīng)用團(tuán)隊(duì)都是直接使用,也沒(méi)有做到基于用戶(hù)群組的權(quán)限隔離。最新版本的ES提供了開(kāi)源免費(fèi)的基本安全策略,可以通過(guò)用戶(hù)群組權(quán)限來(lái)避免客戶(hù)端應(yīng)用的無(wú)意識(shí)操作。
3、全面的知識(shí)體系
本次案例中,先從集群后端運(yùn)行分析,到應(yīng)用程序端源碼分析,再到本地環(huán)境模擬測(cè)試,涉及到的技術(shù)點(diǎn)非常的寬泛,并不能從單一維度發(fā)現(xiàn)解決,也不能僅僅從ES知識(shí)層面排查解決;任何人都不能只從ES集群運(yùn)行表象定位問(wèn)題,很多問(wèn)題爆發(fā)是屬于末端,但引起的其實(shí)在另外一端,這就需要跨界的能力與思維,當(dāng)然最重要的是構(gòu)建自己的知識(shí)體系,有自己獨(dú)立的解決問(wèn)題排查思路,也得掌握必要的各種工具軟件,不能僅僅局限在ES范圍之內(nèi)。
為了用好ES,我們需要掌握開(kāi)發(fā)技能,熟練使用ES提供的開(kāi)發(fā)特性,了解ES各種特性的邊界,防止濫用。我們需要掌握ES集群架構(gòu)基本的原理,基本的運(yùn)行機(jī)制,避免認(rèn)知上的誤區(qū),如ES是典型的主從架構(gòu)分布式,并不是無(wú)中心的分布式。我們需要掌握常規(guī)的運(yùn)維技能,從操作系統(tǒng)基礎(chǔ)環(huán)境,到ES運(yùn)行各種指標(biāo)信息等。
4、全棧工程師理念
隨著業(yè)務(wù)需求與社會(huì)發(fā)展,我們更多的是需要全棧式的工程師,當(dāng)然必須聲明,不是要求一個(gè)工程師同時(shí)兼任多種工作,不是按照國(guó)內(nèi)某些企業(yè)“壓榨式的全棧”。而是特別強(qiáng)調(diào)工程師的專(zhuān)業(yè)水平,工程師可以依據(jù)工作崗位比較容易切換角色,不僅僅局限某一個(gè)固定職位。很多優(yōu)秀的IT產(chǎn)品都不是本職工作的人做出來(lái)的,而是一些跨界的人士創(chuàng)作出來(lái)的。
本次案例中,看似集群的問(wèn)題是服務(wù)端,但實(shí)際上是由于開(kāi)發(fā)知識(shí)面局限造成的,最后解決也是在應(yīng)用端修改代碼解決,這是一個(gè)典型的跨界問(wèn)題,由服務(wù)端逐步往前發(fā)現(xiàn)是應(yīng)用端的問(wèn)題。為了模擬生產(chǎn)環(huán)境問(wèn)題,需要用壓測(cè)工具,這貌似又屬于測(cè)試職責(zé),但為了解決問(wèn)題,從后往前。為了確定線(xiàn)程池設(shè)置問(wèn)題,下載ES對(duì)應(yīng)版本源碼,去查看閱讀對(duì)應(yīng)線(xiàn)程池的設(shè)置,因?yàn)楣俜轿臋n沒(méi)有。為了確定客戶(hù)端應(yīng)用代碼問(wèn)題,基于客戶(hù)開(kāi)發(fā)人員提供的信息,編寫(xiě)模擬客戶(hù)端應(yīng)用代碼行為。
目前國(guó)內(nèi)的大多數(shù)公司工程師都是單一職責(zé)職位與技能,尤其是注重前后端分離之后,前端與后端技能分裂的更嚴(yán)重了,前端很多薪資很高,漲幅快,看不起后端,后端也逐步遠(yuǎn)離前端應(yīng)用,更加不關(guān)心前端運(yùn)行方式;后端應(yīng)用與大數(shù)據(jù)開(kāi)發(fā)也是,將大數(shù)據(jù)開(kāi)發(fā)與應(yīng)用開(kāi)發(fā)分離,導(dǎo)致工程師的專(zhuān)業(yè)素養(yǎng)下降很快,不少大數(shù)據(jù)工程師都不具備很好的編程能力,這是值得大家思考的問(wèn)題。
>>>>
參考資料
State 參考文檔
https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-state.html
threadpool參考文檔
https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-threadpool.html
elasticsearch transport client 參考文檔
https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/index.html
spring data elasticsearch 參考文檔
https://docs.spring.io/spring-data/elasticsearch/docs/4.2.6/reference/html/#reference
jmeter http request 參考文檔
http://jmeter.apache.org/usermanual/component_reference.html#HTTP_Request
dbaplus社群歡迎廣大技術(shù)人員投稿,投稿郵箱:editor@dbaplus.cn
總結(jié)
以上是生活随笔為你收集整理的由Elasticsearch的API命令,引发的金融业生产故障的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 苹果CMSv10首款原创支持百度mip技
- 下一篇: 那些喜欢的句子