Logstash Multiple Pipelines

sparkdev發表於2019-06-28

作為生產者和消費者之間資料流的一箇中心元件,需要一個 Logstash 例項負責驅動多個並行事件流的情況。預設情況下,這樣的使用場景的配置讓人並不太開心,使用者會遭遇所謂的條件地獄(Conditional hell)。因為每個單獨的 Logstash 例項預設支援一個管道,該管道由一個輸入、若干個過濾器和一個輸出組成,如果要處理多個資料流,就要到處使用條件判斷。

條件地獄(Conditional hell)

已知的在一個管道中實現多個獨立流的方法是使用條件判斷。主要方式是在輸入部分透過標籤標記事件,然後在過濾器中和輸出階段建立條件分支,對貼有不同標籤的事件,應用不同的外掛集。這種方式雖然可以解決問題,但在實際的使用中卻非常的痛苦!下面是一個簡單的 demo 片段:

input {
  beats { port => 3444  tag => apache   }
  tcp { port => 4222  tag => firewall   }
}
filter {
   if "apache" in [tags] {  
    dissect { ... }
   } else if "firewall" in [tags] {  
    grok { ... }
   }  
}
output {
   if "apache" in [tags] {  
    elasticsearch { ... }
   } else if "firewall" in [tags] {  
    tcp { ... }
   }  
}

對應的 Logstash 管道配置已經被條件語句包裹的十分臃腫,而它們的唯一目的是保持流的獨立性。
雖然使用條件實現獨立的多個流是可行的,但是很容易看出,由於存在單個管道和處理的單個階段,隨著複雜性的增加,配置會變得非常冗長,很難管理。下圖展示了包含兩個流的簡單管道:

不幸的是,這並不是該方案的唯一缺陷。

缺乏擁塞隔離

如果您熟悉 Logstash 的工作原理,就會知道管道的輸出部分接收到一批事件,並且在所有事件和完成所有輸出之前不會移動到下一批事件。這意味著,對於上面的管道,如果 TCP 套接字目標不可達,Logstash將不會處理其他批次的事件,這也就意味著 Elasticsearch 將不會接收事件,並且會對 TCP 輸入和 Beats 輸入施加反壓力。

不同的資料流需要以不同的方式處理

如果 TCP - > Grok - > TCP 資料流處理大量的小資料,而 Beats -> Dissect -> ES 資料流中的單個資料體積大但是數量少。那麼前一個資料流希望有多個 worker 並行並其每一批次處理更多事件,第二個資料流則期望使用少量的 worker 和每批次處理少量的事件。使用單個管道,無法為單個資料流指定獨立的管道配置。

透過多個 Logstash 例項解決問題

上述問題可以透過在同一臺機器上執行多個 Logstash 例項來解決,然後可以獨立地管理這些例項。但是即使這樣的解決方案也會產生其他問題:

  • 需要管理多個例項(透過 init 系統管理多個後臺服務)
  • 每個 Logstash 的例項也意味著一個獨立的 JVM
  • 需要監視每個 Logstash 例項

這種方式其實很糟糕!

多個管道

從 Logstash 6.0 開始,引入了 Multiple Pipelines,才完美的解決了這個問題。Multiple Pipelines 的配置非常簡單:在配置檔案  pipelines.yml 中新增新的 pipeline 配置並指定其配置檔案就可以了。下面是一個簡單的 demo 配置:

- pipeline.id: apache
  pipeline.batch.size: 125
  queue.type: persisted
  path.config: "/path/to/config/apache.cfg"
  queue.page_capacity: 50mb
- pipeline.id: test
  pipeline.batch.size: 2
  pipeline.batch.delay: 1
  queue.type: memory
  config.string: "input { tcp { port => 3333 } } output { stdout {} }"

這個 YAML 檔案包含一個雜湊(或字典)列表,其中每個雜湊表示一個管道,鍵和值為該管道設定名稱。被省略的設定值返回到它們的預設值。

配置多個管道

下面來看一個真實點的例子,筆者在 Ubuntu 18.04 Server 中安裝了 Logstash 6.2.4,除了在預設的配置檔案目錄(/etc/logstash/conf.d)中新增配置檔案外,建立新的目錄 /etc/logstash/myconf.d,並在 /etc/logstash/myconf.d 目錄下建立 Logstash 配置檔案 krtest.conf。然後在 /etc/logstash/pipelines.yml 檔案中新增新的 pipeline 配置:

- pipeline.id: main
  path.config: "/etc/logstash/conf.d/*.conf"
- pipeline.id: krtest
  path.config: "/etc/logstash/myconf.d/krtest.conf"

其中 pipeline.id 為 main 的管道是預設的配置,我們新新增了 id 為 krtest 的管道並指定了對應的配置檔案路徑。啟動 Logstash,如果你安裝的 X-Pack 外掛就可以在 Kibana->Monitoring->Logstash 中看到新新增的名稱為 krtest 的管道:

使用 Multiple Pipelines 後,我們的 Logstash 配置檔案就可以寫得像下面的程式碼一樣簡練(不再需要那麼多的條件語句)了:

input {
    beats {
        port => 5064
    }
}
filter {
    grok { ... }
}
output {
    elasticsearch { ... }
}

參考:
Multiple Pipelines
Introducing Multiple Pipelines in Logstash

相關文章