解決elasticsearch java client連接慢

隨著數據的積累,傳統的數據庫搜索已經不能滿足業務的需要,這時很多人就開始考慮使用搜索服務。然後在眾多的開源搜索產品中,elasticsearch是比較出色的一個,也比較容易上手。尤其是es強大的搜索功能和存儲功能,基本能滿足絕大多數的業務場景。

但是很多新手在使用elasticsearch的時候,都會遇到一個頭疼的問題,就是elasticsearch的java client連接速度特別慢,大概要2000ms ~ 3000ms,在第一次連接的時候是很讓人煩惱的,但是隨後繼續使用就會非常快。可是如果設計成單例的話,如果不是連續的使用,又必須關閉連接,否則會超時,超時後再使用就會拋出caught on transport layer錯誤。

為了解決這樣一個問題,我們可以設計一個es client 的連接池,只需要維護一定數量的活躍的TransportClient就可以了,這樣在每次使用的時候只需要從連接池中獲取一個活躍的連接來使用就行,這樣就能省下每次連接的2000+ms。具體的實現思路如下:

  1. 首先連接池需要一個容量,容量要控制好,不然會對elasticsearch服務造成太大的壓力。這裡我們定義一個corePoolSize這個變量來表示連接池的容量。

  2. 我們還需要一個緩衝容量,當連接池容量用完的時候可以繼續創建。用變量maxnumPoolSize表示。

  3. 維護TransportClient 我們用Stack數據結構,之所以用Stack後面再解釋。

  4. 維護工作中的TransportClient使用HashSet數據結構。

接下來我們定義EsClientPoolService這樣一個類,這就是我們使用es client的主要服務類了,該類設置成單例模式

解決elasticsearch java client連接慢

單例模式的連接池服務類

在構造函數中我們加入es的鏈接初始化

解決elasticsearch java client連接慢

初始化連接池Client

可以從外部配置文件讀取連接池的初始容量和最大容量,初始化的時候創建初始化的連接Client。因為連接是會超時的,所以我們需要在超時之後定時的去維護Client的連接,所以我們還需要一個定時刷新的job。

解決elasticsearch java client連接慢

定時刷新連接

看到定時刷新這個方法就知道為什麼選擇Stack作為連接池存儲的數據結構了,因為需要把最活躍的鏈接壓入棧頂,保證每次出棧的Client基本是可用的,而不是超時的。然後從棧的前端取出超時的Client,激活後重新入棧。

解決elasticsearch java client連接慢

獲取活躍Client方法

獲取活躍的Client後需要放入工作的Set集合內,用完之後再入連接池存儲棧,可以循環使用,並且剛用完的Client是非常活躍的,查詢速度也比較快。

解決elasticsearch java client連接慢

關閉和銷燬Client連接方法

最後是關閉Client連接和銷燬重建連接池的方法。經過上面的幾個步驟,一個簡單的Elasticsearch Java Client基本上就成功了。這裡有幾點問題需要注意:

  1. 長時間不用,突然使用時,有時候會剛好碰到取出的Client是超時的,並且還沒來得及刷新,這樣的話就會報錯了,解決這個問題可以使用錯誤嘗試機制。

  2. 剛好在刷新的時候有使用連接,因為刷新是從Stack的前端獲取,會導致Stack的重排,這個時候就會比較慢,經測試在1000ms ~ 2000ms之間,不會太慢。

  3. 需要根據實際環境配置連接池的大小,否則有可能會更加慢。

上面都是個人的思路,並已經實現了在生產環境中的基本可用,但還有不少問題沒有測試,沒有暴露出來。我在這裡只是拋磚引玉,如果有更好的辦法或者更好的實現,可以分享出來一起討論。

相關推薦

推薦中...