操做系統和進程部分html
操做系統和進程部分的含義是很清楚的,這裏不會描述的很詳細。他們列出了基本的資源統計,例如CPU和負載。操做系統部分描述了整個操做系統的狀況,進程部分只是描述了Elasticsearch的JVM進程的使用狀況。java
這顯然是頗有用的統計, 可是每每會被忽視,一些統計包括以下部分:node
>CPU
>負載
>內存使用狀況
>swap使用狀況
>打開文件句柄數ios
JVM部分
jvm部分包含一些有關於運行elasticsearch的jvm進程的關鍵信息。最重要的是,它包含了垃圾回收方面的細節,這對你的elasticsearch的集羣的穩定性有很大影響。程序員
>垃圾收集(GC)入門算法
在咱們描述這個以前,頗有必要先介紹下GC以及它對elasticsearch的影響。若是你對jvm中的GC很熟悉,能夠跳過這一章。數據庫
java是一個本身進行垃圾回收的語言,也就是說程序員不須要主動管理內存的分配和釋放。程序員只要專心寫本身的代碼,java虛擬機會管理根據須要分配內存的過程,而後當內存再也不使用的時候,它本身會去釋放。api
當內存被分配給JVM進程,它會被分配成一個叫堆的大塊區域。JVM會把這個堆分紅兩組,叫作「代」:緩存
年輕代(或者伊甸園)服務器
新實例化的對象就在這裏分配空間,年輕代的空間一般很小,大約100MB-500MB。年輕代包含兩個倖存者區域
老年代
存儲那些老的對象的區域。這些對象是長期存在,而且持續很長時間。老年代一般比年輕代大不少。你能夠看到elasticsearch節點的老年代可能大到30GB
當一個對象被實例化後,它會被放置到年輕代,當年輕代的空間滿了,一個年輕代的垃圾回收就啓動了。那些仍然存活的對象就會被移動到其中一個倖存者區域。而死了的對象就會被清除了。若是一個對象在年輕代中經歷了屢次GC仍然倖存,那它將被晉升到老年代。
相似的過程也發生在老年代,當老年代的空間愈來愈滿了,一個垃圾回收就啓動了,同時死了對象會被清除。
天下沒有免費的午飯,年輕代和老年代的垃圾回收都包含一個「stop-the-world」的階段。在這個時間內,JVM會中止程序的執行,進行對象的標記和收集,在這個stop-the-world的階段,沒有任何事情發生,請求不會被處理,ping不會被會迴應。shards不會再進行遷移。整個世界真的中止了。
對於年輕代這不是一個問題,由於它很小,GC執行的很快。可是對於大一點的老年代,緩慢的GC意味着1s甚至15s的停頓,這對於一個服務器軟件來講是不可接受的。
垃圾回收在JVM是很複雜的算法,爲了減小停頓作了不少的工做。同時Elasticsearch很努力適應GC,好比經過內部對象的重用,利用網絡緩衝區,並挺貴一些特徵值例如文檔的數量。可是GC的頻率和長短是須要你特別留意的信息,由於它是集羣不穩定的頭號元兇。
若是一個集羣常常性的發生長時間GC,那麼你的集羣必定內存不足而且負載特別高。這些長時間GC會致使節點週期性的脫離集羣。這種不穩定會致使分片數據不斷的從新生成,以保證集羣內的平衡以及足夠的分片數量。這會增長網絡貸款和磁盤IO,同時你的集羣還要承擔進行正常的索引數據和查詢。
簡而言之,長時間的GC是很糟糕的,須要儘量的減小。
由於GC對Elasticsearch如此重要,你必須對node stats的API顯示的這個部分特別熟悉才行。
"jvm": { "timestamp": 1408556438203, "uptime_in_millis": 14457, "mem": { "heap_used_in_bytes": 457252160, "heap_used_percent": 44, "heap_committed_in_bytes": 1038876672, "heap_max_in_bytes": 1038876672, "non_heap_used_in_bytes": 38680680, "non_heap_committed_in_bytes": 38993920,
jvm部分首先列出的是有關堆內存使用狀況的通常狀況,你能夠看到多少heap被用到,有多少能夠被使用(已經分配了線程),還有堆內存最大能夠長到多少。理想狀況下heap_committed_in_bytes應該和heap_max_in_bytes相同,若是被分配的堆較小,那JVM將會不得不調整堆的大小,這個過程代價是很高的。若是你的這兩個值是不一樣的,請看《Heap: Sizing and Swapping》章節,確認你配置的是否正確。
heap_used_percent 是你必須盯着看的一個有用的參數。Elasticsearch配置的是當堆使用到75%的時候進行GC,若是你的節點老是大約75%,那你節點正在承受內存方面的壓力,這是一個告警,預示着你不久就會出現慢GC。
若是你的heap使用率一直在85%以上,那你有麻煩了,90-95%的機率會由於10-30s的GC 發生性能問題,這仍是好的,最壞的就是發生內存溢出。
"pools": { "young": { "used_in_bytes": 138467752, "max_in_bytes": 279183360, "peak_used_in_bytes": 279183360, "peak_max_in_bytes": 279183360 }, "survivor": { "used_in_bytes": 34865152, "max_in_bytes": 34865152, "peak_used_in_bytes": 34865152, "peak_max_in_bytes": 34865152 }, "old": { "used_in_bytes": 283919256, "max_in_bytes": 724828160, "peak_used_in_bytes": 283919256, "peak_max_in_bytes": 724828160 } } },
young, survivor, and old sections 顯示了每一個代在GC中的使用狀況,供你分析。這些數據方便你看到他們的相對大小,可是對於你調查問題每每不是很重要。
gc": { "collectors": { "young": { "collection_count": 13, "collection_time_in_millis": 923 }, "old": { "collection_count": 0, "collection_time_in_millis": 0 } } }
gc區域顯示的GC的次數和時間,包括年輕代和老年代。大部分時間,你能夠忽略關於年輕代的手機次數,這個次數每每很大,這是很正常的。
相反,老年代的GC應該少一點,collection_time_in_millis也要小。這是個累計數字,很難給你一個你應該擔憂時候的數字(舉個例子,一個節點運行了一年,可能有不少次GC,可是這個節點卻很健康穩定)。這也是一些工具例如Maverl特別有用的緣由。多長時間內的GC次數是個很重要的考慮因素。
花在GC上的時間也很重要,例如,在索引數據的時候會產生必定量的內存垃圾,這很正常,會讓GC不時的發生。這些GC一般都是很快的,對節點也沒有多少英雄。年輕代只須要一兩毫秒。老年代可能須要幾百毫秒。這和十秒級的GC是很大不一樣的。
咱們最佳的建議是週期性的收集GC的個數和時間(或者使用Marverl) 而且留意頻繁GC,你也能夠打開慢GC日誌,記錄在日誌裏。
ThreadPool部分
Elasticsearch 內部使用了線程池,經過這些線程池之間的合做完成工做,在須要時傳遞工做。通常來講你不須要調整和優化線程池。可是有時候你看着這些線程池的狀態,對你掌握你的集羣行爲是頗有幫助的。
這有十幾個線程池,他們的格式都是相似的:
"index": { "threads": 1, "queue": 0, "active": 0, "rejected": 0, "largest": 1, "completed": 1 }
每一個線程都列出了配置的線程數,其中有多少個線程是正在處理事務的,也就是活動的,還有多少等待處理的事務在隊列裏。
若是隊列滿了,超出了限制,新的事務就會開始被拒絕,你能夠看到拒絕的事務的統計,這一般表示你的集羣正處在一個資源瓶頸,由於一個滿的隊列表示你的集羣或者節點正在以最大的速度處理事務,可是依然趕不上新事務增長的速度。
關於bulk的拒絕
若是你的線程隊列出現拒絕請求的事情,那麼醉有可能發生的就是bulk批量索引的請求,經過採用併發導入線程,很容易發給elasticsearch不少的bulk請求,併發請求越多越好嗎?
現實中,任何集羣都有必定的線程,形成入不敷出。一旦這個閾值達到了,你的隊列就會被迅速的填滿,新的bulk請求就會被拒絕。
這是一個好事,隊列的拒絕是對壓力的一個有效措施,他們告訴你你的集羣正在處於最大的容量,這要好過把數據所有塞到內存隊列裏。增大隊列大小不會提高性能,它只會隱藏問題,若是你的集羣每秒只能處理1萬個文檔,這和你的隊列大小是100仍是一千萬沒有任何關係,你的集羣每秒的處理能力仍然是1萬個文檔。
隊列只會隱藏性能問題,而且帶來數據丟失的風險,在隊列裏的表示尚未被處理的,若是你的節點掛了,那麼這些請求就會永遠的丟失了,此外隊列會消耗很大的內存,這不是個好主意。
最好咱們經過優雅的解決隊列滿了的問題來清理隊列。當你遇到bulk拒絕請求時候,你應該採起以下措施:
一、中止插入線程3-5秒
二、從bluk請求裏提取被拒絕的操做,可能大部分請求都成功了。bulk的響應裏會告訴你哪些操做成功了,哪些操做被拒絕了。
三、把拒絕的操做從新生成一個新的bulk請求。
四、若是再有拒絕請求發生,就重複上面的步驟。
經過這種方式,你的代碼會天然的適應你的集羣的負載,天然的減壓。
請求拒毫不是錯誤,它們只是表示你須要過會重試。
有十幾個線程池,大部分你能夠忽視,可是有少部分須要你特別注意:
indexing 正常的索引文檔的請求
bulk 批量請求,這有區別於非批量的請求
get 根據id獲取文檔的操做
search 索引的檢索和查詢請求
merging 專門管理lucene合併的線程池
FS和Network部分(剩餘空間和網絡)
繼續看node stats api返回的信息,你會看到一個關於文件系統的統計信息,剩餘空間,數據存放目錄,磁盤io等待。若是你沒有監控剩餘磁盤空間大小,你能夠從這裏獲得。磁盤io也是很容易獲得,可是一些更專業的命令行工具(例如iostat)可能更有用。
很顯然,若是你的磁盤空間不足了,elasticsearch確定完蛋了,因此必定要保證充足的磁盤空間。
下面是關於network統計的兩個部分:
"transport": { "server_open": 13, "rx_count": 11696, "rx_size_in_bytes": 1525774, "tx_count": 10282, "tx_size_in_bytes": 1440101928 }, "http": { "current_open": 4, "total_opened": 23 },
transport: 顯示了網絡傳輸的基本信息,這涉及到節點之間的通訊(一般是9300端口)和一些客戶端和節點之間的連接。若是你看到不少連接在這裏,不要擔憂,elasticsearch會保持大量的節點之間的連接。
http表示關於http端口(一般是9200)的基本信息,若是你看到一個很是大的total_opened,而且在不斷增長,這是一個很明確的信號:你的客戶端沒有使用HTTP的keep-alive。keep-alive的連接對性能很重要,由於不斷的建立和斷開socket連接是很昂貴的(同事也會浪費open files個數),確保你的客戶端都使用了正確的配置。
Circuit Breaker(斷路器)
最後咱們來到最後一個部分,關於fieldata 阻斷的統計(在《Circuit Breaker》章節中有介紹。
"fielddata_breaker": { "maximum_size_in_bytes": 623326003, "maximum_size": "594.4mb", "estimated_size_in_bytes": 0, "estimated_size": "0b", "overhead": 1.03, "tripped": 0 }
這裏,你能夠看到最大阻斷的大小(例如,你的查詢請求使用多大的內存的時候,這個斷路器就會進行左右)。這個部分就是告訴你斷路器發揮做用的次數,以及當前配置的過載值,這個值是用來估計的(譯者注:用來估計查詢可能須要使用的內存)。由於有些查詢比其它的比較難估計。
最主要的東西仍是關於斷路器起做用的次數的統計,若是這個值很大而且持續增長,表示你的查詢須要優化,或者你須要更多的內存(總體上增長內存,或者增長更多的節點)。
原文地址:https://www.elastic.co/guide/en/elasticsearch/guide/current/_monitoring_individual_nodes.html
[翻譯]Elasticsearch重要文章之三:重要配置項的修改
Elasticsearch已經有很好的默認值,特別是涉及到性能相關的配置或者選項。若是你有什麼拿不許的,最好就不要動它。咱們已經目擊了數十個由於錯誤的設置而致使集羣毀滅,由於它的管理者總認爲他改動一個配置或者選項就能夠帶來100倍的提高。
注意:請閱讀全文,全部的配置項都同等重要,和描述順序無關,請閱讀全部的配置選項,並應用到你的集羣中。
其它數據庫可能須要調優,但總得來講,Elasticsearch不須要。若是你遇到了性能問題,最好的解決方法一般是更好的數據佈局或者更多的節點。在Elasticsearch中有不多的」神奇的配置項」,若是存在,咱們也已經幫你優化了。
指定名字
Elasticsearch默認啓動的集羣名字叫elasticsearch,你最好給你的生產環境的集羣改個名字,更名字的目的很簡單,就是防止某我的的筆記本加入到了集羣,形成意外。簡單修改爲elasticsearch_production ,會省掉屢次心痛~。
你能夠在你的elasticsearch.yml中修改:
cluster.name: elasticsearch_production
一樣,修改節點的名字也是明智的,就像你如今可能發現的那樣,Elasticsearch會在你的節點啓動的時候隨機給它指定一個名字。這在你開發的時候可能以爲很萌,可是當凌晨3點鐘,你還在嘗試會議哪臺物理機是Tagak the Leopard Lord.的時候,你就不以爲萌了。
更重要的是,這些名師是在啓動的時候產生的,每次啓動節點,它都會獲得一個新的名字,這可使日誌混淆,由於全部節點的名稱都是不斷變化的。
這些可能性都是很無聊的,咱們建議你給每一個及誒點一個有意義的名字-一個清楚的,描述性的名字,一樣你能夠在elasticsearch.yml中配置:
node.name: elasticsearch_005_data
路徑
默認狀況下,Eleasticsearch會把插件、日誌以及你最重要的數據放在安裝目錄下。這會帶來不幸的事故。即若是你從新安裝Elasticsearch的時候就可能不當心把安裝目錄覆蓋了,若是你不當心,你就可能把你的所有數據刪掉了。
不要笑,這種狀況,咱們見過不少次了。
最好的選擇就是把你的數據目錄配置到安裝目錄之外的地方,一樣你也能夠選擇轉移你的插件和日誌目錄。
能夠更改以下:
path.data: /path/to/data1,/path/to/data2
# Path to log files:
path.logs: /path/to/logs
# Path to where plugins are installed:
path.plugins: /path/to/plugins
注意:你能夠經過逗號分隔指定多個目錄。
數據能夠保存到多個不一樣的目錄,每一個目錄若是是掛載在不一樣的硬盤,作一我的RAID 0是一個簡單而有效的方式。Elasticsearch會自動把數據分隔到不一樣的目錄,以便提升性能。
最小主節點數
minimum_master_nodes的設定對你的集羣的穩定及其重要,當你的集羣中有兩個masters的時候,這個配置有助於防止集羣分裂。
若是你發生了一個集羣分裂,你集羣就會處在丟失數據的危險中,由於master節點是被認爲是這個集羣的最高統治者,它決定了何時新的索引能夠建立,多少分片要移動等等。若是你有兩個master節點,你的數據的完整性將得不到保證,由於你有兩個master節點認爲他們有集羣的控制權。
這個配置就是告訴Elasticsearch當沒有足夠master候選節點的時候,就不要進行master選舉,等master候選節點足夠了才進行選舉。
該配置必須應該配置成master候選節點的法定個數(大多數個),法定個數就是(master候選節點個數/2)+1. 這裏有幾個例子:
*若是你有10個節點(能保存數據,同時能成爲master) 法定數就是6
*若是你有3個候選master,和100個數據節點,法定數就是2,你只要數數那些能夠作master的節點數就能夠了。
*若是你有兩個節點,你遇到難題了,法定數固然是2,可是這意味着若是有一個節點掛掉,你整個集羣就不可用了。設置成1能夠保證集羣的功能,可是就沒法保證集羣分裂了,像這樣的狀況,你最好至少保證有3個節點。
elasticsearch.yml中這樣配置:
discovery.zen.minimum_master_nodes: 2
可是因爲ELasticsearch是動態的,你能夠很容易的添加和刪除節點,這會改變這個法定個數,若是你不得不修改索引的節點的配置而且重啓你的整個集羣爲了讓配置生效,這將是很是痛苦的一件事情。
基於這個緣由,minimum_master_nodes (還有一些其它配置),容許經過API調用的方式動態進行配置,當你的集羣在線運行的時候,你能夠這樣修改配置:
PUT /_cluster/settings
{
「persistent」 : {
「discovery.zen.minimum_master_nodes」 : 2
}
}
這將成爲一個永久的配置,而且不管你配置項裏配置的如何,這個將優先生效。當你添加和刪除master節點的時候,你須要更改這個配置。
集羣恢復方面的配置項
當你集羣重啓時,幾個配置項影響你的分片恢復的表現。首先,咱們必須明白,若是什麼也沒配置將會發生什麼。
想象一下假設你有10個節點,每一個節點保存一個分片,主分片或者副分片,也就是有一個有5個主分片/1個副本 的索引。你須要中止整個集羣進行休整(舉個例子,爲了安裝一個新的驅動程序)。當你重啓你的集羣,很天然會出現5個節點已經起動了,還有5個還沒啓動的場景。
假設其它五個節點出問題,或者他們根本沒有收到當即重啓的命令。不管什麼緣由,你只要五個節點在線上。這五個節點會相互通訊,選出一個master,從而造成一個集羣,他們注意到數據再也不均勻分佈,由於有個節點在集羣中丟失了,他們之間會立馬啓動分片複製。
最後,你的其它5個節點打開加入了集羣,這些節點會發現他們的數據已經成爲其它節點的副本了,因此他們刪除本地數據(由於這份數據要麼是多餘的,要麼是過期的)。而後整個集羣從新進行平衡,由於集羣的大小已經從5變成了10。
在整個過程當中,你的節點會消耗磁盤和網盤,來回移動數據,由於沒有更好的理由。對於有上T數據的大集羣,這種數據的傳輸須要很長時間。若是等待全部的節點重啓好了,整個集羣再上線,全部的本地的數據都不須要移動。
如今咱們知道問題的所在了,咱們能夠修改一個小配置就能夠緩解這個事情,首先咱們要給ELasticsearch一個嚴格的限制:
gateway.recover_after_nodes: 8
這將放置Elasticsearch進行數據恢復,在發現8個節點(數據節點或者master節點)以前。這個值的設定取決於我的喜愛: 整個集羣提供服務以前你但願有多少個節點在線?咱們設置爲8, 這意味着至少要有8個節點,該集羣纔可用。
如今咱們要告訴Ealsticsearch集羣中應該有多少個節點,而且咱們但願集羣須要多久等待全部節點:
gateway.expected_nodes: 10
gateway.recover_after_time: 5m
這意味着Elasticsearch會採起以下操做:
*至少等待8個節點上線
*等待5分鐘,或者10個節點上線後,才進行數據恢復,這取決於哪一個條件先達到。
這三個設置能夠在集羣重啓的時候避免過多的分片交換。這可能會讓數據恢復從數個小時縮短爲幾秒鐘。
這些配置只能設置在config/elasticsearch.yml文件中,或者是在命令行裏(這些配置是沒法東塔修改的),它們只在整個集羣重啓的時候有實質性做用。
最好使用單播代替組播
Elasticsearch默認是被配置成使用多播發現節點。多播就是經過在你的網絡中發送UDP的ping請求以發現節點,其它Elasticsearch會收到這些ping請求而且進行響應,這樣隨後就會造成一個集羣。
多播對於開發環境是很好的,你不須要作什麼事情,打開一些節點,他們天然的會發現對方造成一個集羣。
正是由於這種易用性,你在生產環境中必須禁掉它。否在你獲得的結果就是一個節點意外的加入到了你的生產環境,由於他們收到了一個錯誤的組播信號。對於組播自己並無錯。組播會致使一些愚蠢的問題,而且致使集羣變的脆弱(例如:一個網絡工程師正在搗鼓網絡,而沒有告訴你,你會發現全部的節點忽然發現不了對方了)。
在生產環境中,建議使用單播代替組播,也就是說爲Elasticsearch提供一些它應該去嘗試鏈接的節點列表。一旦這個節點聯繫到組播列表中的一員,它就會獲得整個集羣全部節點的狀態,而後它會聯繫master節點,並加入集羣。
這意味着你的單播列表不須要包含你的集羣中的全部節點,它只須要包含足夠一個新節點聯繫上其中一個而且說上話就ok了。若是你使用master候選節點做爲單播列表,你只要列出三個就能夠了。這個配置在elasticsearch.yml文件中:
discovery.zen.ping.multicast.enabled: false
discovery.zen.ping.unicast.hosts: [「host1」, 「host2:port」]
備註:請確認你已經關閉了組播(discovery.zen.ping.multicast.enabled: false),不然它會和單播同時存在。
Elasticsearch重要文章之四:監控每一個節點(Indices部分)
集羣的健康只是一個方面,它是對整個集羣全部方面的一個很高的歸納。節點狀態的api是另一個方面,它提供了關於你的集羣中每一個節點令你眼花繚亂的統計數據。
節點的狀態提供了那麼多的統計數據,在你很熟悉它們執勤,你可能不肯定哪些指標是相當重要。咱們會把須要監控的最重要的幾個指標跳出來(咱們建議你把全部的統計指標記錄下來,例如使用Marvel插件,由於你不知道你哪天可能就須要)。
節點狀態的API能夠經過下面的方式執行
GET _nodes/stats
在輸出內容的開頭,咱們能夠看到集羣的名字和咱們第一個node的信息:
{ "cluster_name": "elasticsearch_zach", "nodes": { "UNr6ZMf5Qk-YCPA_L18BOQ": { "timestamp": 1408474151742, "name": "Zach", "transport_address": "inet[zacharys-air/192.168.1.131:9300]", "host": "zacharys-air", "ip": [ "inet[zacharys-air/192.168.1.131:9300]", "NONE" ], ...
節點會根據一個hash值的順序來顯示,也就是node的uuid值。還有一些關於node的網絡屬性會顯示(例如傳輸地址和HOST)。這些信息有助於調試發現問題,好比那些節點沒有加入集羣。一般你可能會發現端口用錯了,或者節點綁錯了IP地址等等。
Indices部分
indices部分列出的是對於全部的索引在該節點上的彙總信息。
"indices": { "docs": { "count": 6163666, "deleted": 0 }, "store": { "size_in_bytes": 2301398179, "throttle_time_in_millis": 122850 },
它返回的統計信息能夠分紅這樣幾個部分:
docs: 顯示有多少文檔在該節點,以及有多少刪除的文檔尚未從數據段中清除出去。
store: 顯示該節點消耗了多少物理存儲,這個數據包含主分片和副分片,若是throttle_time_in_millis太大,說明你設置的磁盤流量過低(參考段的合併一章節)
"indexing": { "index_total": 803441, "index_time_in_millis": 367654, "index_current": 99, "delete_total": 0, "delete_time_in_millis": 0, "delete_current": 0 }, "get": { "total": 6, "time_in_millis": 2, "exists_total": 5, "exists_time_in_millis": 2, "missing_total": 1, "missing_time_in_millis": 0, "current": 0 }, "search": { "open_contexts": 0, "query_total": 123, "query_time_in_millis": 531, "query_current": 0, "fetch_total": 3, "fetch_time_in_millis": 55, "fetch_current": 0 }, "merges": { "current": 0, "current_docs": 0, "current_size_in_bytes": 0, "total": 1128, "total_time_in_millis": 21338523, "total_docs": 7241313, "total_size_in_bytes": 5724869463 },
indexing: 表示索引文檔的次數,這個是經過一個計數器累加計數的。當文檔被刪除時,它不會減小。注意這個值永遠是遞增的,發生在內部索引數據的時候,包括那些更新操做。
search:列出了主動檢索的次數(open_contexts),查詢總數,以及從節點啓動到如今花在這些查詢上的總時間。query_time_in_millis / query_total的比值能夠做爲你的查詢效率的粗略指標。比值越大,每一個查詢用的時間越多,你就須要考慮調整或者優化。
後面關於fetch的統計,是描述了查詢的第二個過程(也就是query_the_fetch裏的fetch)。fetch花的時間比query的越多,表示你的磁盤很慢,或者你要fetch的的文檔太多。或者你的查詢參數分頁條件太大,(例如size等於1萬)
merges:包含lucene段合併的信息,它會告訴你有多少段合併正在進行,參與的文檔數,這些正在合併的段的總大小,以及花在merge上的總時間。
若是你的集羣寫入比較多,這個merge的統計信息就很重要。merge操做會消耗大量的磁盤io和cpu資源。若是你的索引寫入不少,你會看到大量的merge操做,一低昂要閱讀《關於索引數據性能方面的提示》這一章節。
注意:更新和刪除都會致使大量的合併,由於它們會產生段碎片,這些都須要進行合併。
"filter_cache": { "memory_size_in_bytes": 48, "evictions": 0 }, "id_cache": { "memory_size_in_bytes": 0 }, "fielddata": { "memory_size_in_bytes": 0, "evictions": 0 }, "segments": { "count": 319, "memory_in_bytes": 65812120 }, ...
filter_cache:表示緩存的filter bitset所佔的內存大小,以及一個filter緩存被淘汰的次數。大量的緩存淘汰預示着你可能須要增長你的filter緩存大小,或者你的filter不太適合緩存(例如,你的filter基數比較大,例如緩存當前時間的表達式。譯註:意思就是你的filter基數很大,例如你的某個field是表示當前時間,你的filter確定很大,緩存不容易利用上)
可是淘汰是個很難度量的評價,filter 是被緩存到每一個段(segement)上的,在一個小段上淘汰比在一個大段上淘汰容易一些。若是你有不少淘汰,可是都是發生在小的段上,那對查詢的性能影響也不大。
把這個淘汰的統計做爲一個粗略的指導,若是你看到大量的淘汰,就要調查下你的filter,確保它們是比較適合緩存的。若是filters不斷的淘汰,即使是在小的段上,對性能仍是有影響的,因此你最好使用適合緩存的filter
id_cache:顯示了父子mapping使用的內存,若是你使用了父子映射,id_cache就會在內存裏位置一張連接表包含這種關係,這個統計告訴你多少內存正在使用。由於它和父子文檔的個數有個明確的線性關係,因此對於這部份內存的使用,你能夠作的事情不多,它是常駐內存的,因此你最好常常關注它。
field_data:顯示了fielddata使用的內存,fielddata用於聚合、排序等。這裏也有一個淘汰數,不像filter_cache,這裏的淘汰數頗有用,它必須是0或者接近0,由於fielddata 不是緩存,任何淘汰的代價都是很大的,必需要避免的。若是你看到了淘汰,你必須從新評估你的內存狀況,關於fielddata的限制,以及查詢,或者三者所有。
segments:告訴你當前節點的lucene 段的個數,這多是一個很重要的數字。大多數的索引應該在50到150個段左右,即使是幾T大小的數十億的文檔。大量的段會帶來合併的問題(例如:合併趕不上段的產生)。注意這個統計是對一個節點上全部的索引而言的,記住喲。
其中內存的統計,能夠告訴你Lucene的段自身須要多少內存。這裏包括基礎的數據結構,包括提交列表,詞典,bloom過濾器等。段的數量多會增長承載這些數據結構的開銷,這個內存的使用就是對這個開銷的度量。
監控每一個節點(ThreadPool部分)
ThreadPool部分
Elasticsearch 內部使用了線程池,經過這些線程池之間的合做完成工做,在須要時傳遞工做。通常來講你不須要調整和優化線程池。可是有時候你看着這些線程池的狀態,對你掌握你的集羣行爲是頗有幫助的。
這有十幾個線程池,他們的格式都是相似的:
"index": { "threads": 1, "queue": 0, "active": 0, "rejected": 0, "largest": 1, "completed": 1 }
每一個線程都列出了配置的線程數,其中有多少個線程是正在處理事務的,也就是活動的,還有多少等待處理的事務在隊列裏。
若是隊列滿了,超出了限制,新的事務就會開始被拒絕,你能夠看到拒絕的事務的統計,這一般表示你的集羣正處在一個資源瓶頸,由於一個滿的隊列表示你的集羣或者節點正在以最大的速度處理事務,可是依然趕不上新事務增長的速度。
關於bulk的拒絕
若是你的線程隊列出現拒絕請求的事情,那麼醉有可能發生的就是bulk批量索引的請求,經過採用併發導入線程,很容易發給elasticsearch不少的bulk請求,併發請求越多越好嗎?
現實中,任何集羣都有必定的線程,形成入不敷出。一旦這個閾值達到了,你的隊列就會被迅速的填滿,新的bulk請求就會被拒絕。
這是一個好事,隊列的拒絕是對壓力的一個有效措施,他們告訴你你的集羣正在處於最大的容量,這要好過把數據所有塞到內存隊列裏。增大隊列大小不會提高性能,它只會隱藏問題,若是你的集羣每秒只能處理1萬個文檔,這和你的隊列大小是100仍是一千萬沒有任何關係,你的集羣每秒的處理能力仍然是1萬個文檔。
隊列只會隱藏性能問題,而且帶來數據丟失的風險,在隊列裏的表示尚未被處理的,若是你的節點掛了,那麼這些請求就會永遠的丟失了,此外隊列會消耗很大的內存,這不是個好主意。
最好咱們經過優雅的解決隊列滿了的問題來清理隊列。當你遇到bulk拒絕請求時候,你應該採起以下措施:
一、中止插入線程3-5秒
二、從bluk請求裏提取被拒絕的操做,可能大部分請求都成功了。bulk的響應裏會告訴你哪些操做成功了,哪些操做被拒絕了。
三、把拒絕的操做從新生成一個新的bulk請求。
四、若是再有拒絕請求發生,就重複上面的步驟。
經過這種方式,你的代碼會天然的適應你的集羣的負載,天然的減壓。
請求拒毫不是錯誤,它們只是表示你須要過會重試。
有十幾個線程池,大部分你能夠忽視,可是有少部分須要你特別注意:
indexing 正常的索引文檔的請求
bulk 批量請求,這有區別於非批量的請求
get 根據id獲取文檔的操做
search 索引的檢索和查詢請求
merging 專門管理lucene合併的線程池
FS和Network部分(剩餘空間和網絡)
繼續看node stats api返回的信息,你會看到一個關於文件系統的統計信息,剩餘空間,數據存放目錄,磁盤io等待。若是你沒有監控剩餘磁盤空間大小,你能夠從這裏獲得。磁盤io也是很容易獲得,可是一些更專業的命令行工具(例如iostat)可能更有用。
很顯然,若是你的磁盤空間不足了,elasticsearch確定完蛋了,因此必定要保證充足的磁盤空間。
下面是關於network統計的兩個部分:
"transport": { "server_open": 13, "rx_count": 11696, "rx_size_in_bytes": 1525774, "tx_count": 10282, "tx_size_in_bytes": 1440101928 }, "http": { "current_open": 4, "total_opened": 23 },
transport: 顯示了網絡傳輸的基本信息,這涉及到節點之間的通訊(一般是9300端口)和一些客戶端和節點之間的連接。若是你看到不少連接在這裏,不要擔憂,elasticsearch會保持大量的節點之間的連接。
http表示關於http端口(一般是9200)的基本信息,若是你看到一個很是大的total_opened,而且在不斷增長,這是一個很明確的信號:你的客戶端沒有使用HTTP的keep-alive。keep-alive的連接對性能很重要,由於不斷的建立和斷開socket連接是很昂貴的(同事也會浪費open files個數),確保你的客戶端都使用了正確的配置。
Circuit Breaker(斷路器)
最後咱們來到最後一個部分,關於fieldata 阻斷的統計(在《Circuit Breaker》章節中有介紹。
"fielddata_breaker": { "maximum_size_in_bytes": 623326003, "maximum_size": "594.4mb", "estimated_size_in_bytes": 0, "estimated_size": "0b", "overhead": 1.03, "tripped": 0 }
這裏,你能夠看到最大阻斷的大小(例如,你的查詢請求使用多大的內存的時候,這個斷路器就會進行左右)。這個部分就是告訴你斷路器發揮做用的次數,以及當前配置的過載值,這個值是用來估計的(譯者注:用來估計查詢可能須要使用的內存)。由於有些查詢比其它的比較難估計。
最主要的東西仍是關於斷路器起做用的次數的統計,若是這個值很大而且持續增長,表示你的查詢須要優化,或者你須要更多的內存(總體上增長內存,或者增長更多的節點)。
原文地址:https://www.elastic.co/guide/en/elasticsearch/guide/current/_monitoring_individual_nodes.html