隨著業務的增長,上述方案不僅維護成本奇高,而且難以滿足我們對于精細化數據分析的需求。由于 rsyslog 接收到的數據是一個字符串,而不是 JSON 格式的日志,給日志分析帶來了一定的難度。

計算機領域有句名言: “任何問題都可以通過增加一個間接的中間層來解決”。我們其實也考慮過在 tcp-logger 和 rsyslog 之間再加一個中間層,使字符串轉換為 JSON。但這顯然不是長久之計。

所以我們換了一種思路去看待這個問題:如果把現有架構中的“tcp-logger+rsyslog+Promtail+Loki”看作是一個巨大的中間層,那么不論我們在這中間怎么添加額外的中間層,除了能解決燃眉之急外,只會使它變得更加臃腫和難以維護。市面上有沒有一個產品能直接把“tcp-logger+rsyslog+Promtail+Loki”給替換掉呢?

帶著這個問題,我們花了些時間進行調研,最終選擇 ClickHouse 主要有以下幾點原因。

  1. ClickHouse 提供 HTTP 接口,方便其它模塊調用。
  2. 基于 ClickHouse 的分析工具鏈很成熟,能夠滿足我們對日志分析的需求。
  3. ClickHouse 支持使用對象存儲作為存儲引擎,非常方便。
  4. 沒有必要自己重復“造輪子”。

接下來就只剩下一個問題需要解決了:如何實現 Apache APISIX 和 ClickHouse 之間的對接?以插件的形式實現對接其實是一個不錯的方法。作為 Apache APISIX 社區的一員,我一直都在社區里面“潛水”,看到了最近 Apache APISIX 在生態方面的持續進步,其實我也有些心動,一直在使用 Apache APISIX,但還沒有給社區貢獻過代碼,不如就借這個機會為社區的生態發展添一把火吧。

ClickHouse 插件實現原理

clickhouse-logger插件的作為一個中間層,對接 Apache APISIXClickHouse。如前文所說,我們使用Apache APISIX 作為七層負載均衡,請求經過 Apache APISIX 會產生日志,比如 access log 和 error log。clickhouse-logger 收集到日志后,會按照自身 metadata 所設置的日志格式,對這些日志進行整理。最后依靠批處理器將整理過的日志批量發送至 ClickHouse。

clickhouse-logger 在我們這個場景下,起到了替代“tcp-logger+rsyslog+Promtail+Loki”的作用。免除了多個組件之間的格式轉換和數據轉發,可將 Log 數據請求直接推送到 ClickHouse 服務器。

操作步驟

以下是在一個路由中啟用 clickhouse-logger 插件的示例過程。

啟用 ClickHouse 插件

運行curl 命令,為指定路由開啟 clickhouse-logger 插件。

curl http://127.0.0.1:9080/apisix/admin/routes/1 \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"plugins": {
"clickhouse-logger": {
"user": "default",
"password": "a",
"database": "default",
"logtable": "test",
"endpoint_addr": "http://127.0.0.1:8123"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
},
"uri": "/hello"
}

clickhouse-logger 的參數表如下。

名稱類型必填默認值取值范圍描述
endpoint_addrstringn/an/aClickHouse 服務器的 endpoint。
databasestringn/an/a使用的數據庫。
logtablestringn/an/a寫入的表名 。
userstringn/an/aClickHouse 的用戶。
passwordstringn/aClickHouse 的密碼 。
timeoutinteger3[1,…]發送請求后保持連接活動的時間。
namestring“clickhouse-logger”n/a標識 logger 的唯一標識符。
batch_max_sizeinteger100[1,…]設置每批發送日志的最大條數,當日志條數達到設置的最大值時,會自動推送全部日志到 clickhouse。
max_retry_countinteger0[0,…]從處理管道中移除之前的最大重試次數。
retry_delayinteger1[0,…]如果執行失敗,則應延遲執行流程的秒數。
ssl_verifybooleantrue[true,false]驗證證書。

測試 ClickHouse 插件

  1. 使用 curl 命令測試插件。
curl -i http://127.0.0.1:9080/hello
  1. 返回結果如下,則表示成功啟用。
HTTP/1.1 200 OK
...
hello, world

進階操作 1:設置日志格式

你可以使用 log_format 這個元數據設置自定義的日志格式,示例如下。

  1. 配置 log_format 元數據參數。
curl http://127.0.0.1:9080/apisix/admin/plugin_metadata/clickhouse-logger \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"log_format": {
"host": "$host",
"@timestamp": "$time_iso8601",
"client_ip": "$remote_addr"
}
}'

JSON 格式的鍵值對來聲明日志格式。對于值部分,僅支持字符串。如果是以 $ 開頭,則表明是要獲取 APISIX 變量或 Nginx 內置變量。該設置是全局生效的,意味著指定 log_format 后,將對所有綁定 http-logger 的 Route 或 Service 生效。

  1. 創建 ClickHouse 寫入的表格。
CREATE TABLE default.test (
host String, client_ip String, route_id String, @timestamp String, PRIMARY KEY(@timestamp) ) ENGINE = MergeTree()
  1. 在 ClickHouse 上執行 select * from default.test;,將得到類似下面的數據。
┌─host──────┬─client_ip─┬─route_id─┬─@timestamp────────────────┐
│ 127.0.0.1 │ 127.0.0.1 │ 1 │ 2022-01-17T10:03:10+08:00 │
└───────────┴───────────┴──────────┴───────────────────────────┘

進階操作 2:使用 Grafana 與 ClickHouse 對接

  1. 全局開啟 clickhouse-logger 插件。
curl http://127.0.0.1:9080/apisix/admin/global_rules/1 \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"plugins": {
"clickhouse-logger": {
"timeout": 3,
"retry_delay": 1,
"batch_max_size": 100,
"user": "default",
"password": "a",
"database": "default",
"logtable": "t", "max_retry_count": 1,
"endpoint_addr": "http://127.0.0.1:8123"
}
}
}'
  1. 配置 log_format 元數據參數。log_format 的格式必須與數據庫表的結構保持一致,否則會導致寫入失敗。
curl http://127.0.0.1:9080/apisix/admin/plugin_metadata/clickhouse-logger \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"log_format": {
"upstream_header_time": "$upstream_header_time",
"upstream_connect_time": "$upstream_connect_time",
"status": "$status",
"host": "$host",
"body_bytes_sent": "$body_bytes_sent",
"request": "$request",
"remote_user": "$remote_user",
"client_ip": "$remote_addr",
"content_length": "$content_length",
"local_time": "$fmt_ms_time_local",
"http_referer": "$http_referer",
"http_x_amz_target": "$http_x_amz_target",
"http_x_request_id": "$http_x_request_id",
"upstream_response_time": "$upstream_response_time",
"upstream_status": "$upstream_status",
"http_user_agent": "$http_user_agent",
"request_time": "$request_time",
"upstream_addr": "$upstream_addr",
"http_host": "$http_host",
"content_type": "$content_type"
}
}'

以下是使用 Grafana 與 Clickhouse 對接后的儀表盤視圖。

禁用 ClickHouse 插件

在插件配置中刪除相應的配置即可禁用 clickhouse-logger。由于 Apache APISIX 插件是熱加載模式,因此無需重新啟動即可更新配置。

curl http://127.0.0.1:9080/apisix/admin/routes/1  \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"methods": ["GET"],
"uri": "/hello",
"plugins": {},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
}
}'

總結

以上就是我為 Apache APISIX 開發clickhouse-logger的全過程。希望社區里有更多的人愿意走出舒適區,實現自身的角色轉換,從關注者變為貢獻者的過程遠比你想象的簡單。

文章來源:API gateway integrates ClickHouse plugin to improve the efficiency of full link logging

上一篇:

基于 TiDB 的 API 網關高可用配置最佳實踐

下一篇:

MySQL API:它是什么以及如何在幾分鐘內創建一個
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費