
如何快速實現REST API集成以優化業務流程
隨著業務的增長,上述方案不僅維護成本奇高,而且難以滿足我們對于精細化數據分析的需求。由于 rsyslog 接收到的數據是一個字符串,而不是 JSON 格式的日志,給日志分析帶來了一定的難度。
計算機領域有句名言: “任何問題都可以通過增加一個間接的中間層來解決”。我們其實也考慮過在 tcp-logger
和 rsyslog 之間再加一個中間層,使字符串轉換為 JSON。但這顯然不是長久之計。
所以我們換了一種思路去看待這個問題:如果把現有架構中的“tcp-logger+rsyslog+Promtail+Loki”看作是一個巨大的中間層,那么不論我們在這中間怎么添加額外的中間層,除了能解決燃眉之急外,只會使它變得更加臃腫和難以維護。市面上有沒有一個產品能直接把“tcp-logger+rsyslog+Promtail+Loki”給替換掉呢?
帶著這個問題,我們花了些時間進行調研,最終選擇 ClickHouse 主要有以下幾點原因。
接下來就只剩下一個問題需要解決了:如何實現 Apache APISIX 和 ClickHouse 之間的對接?以插件的形式實現對接其實是一個不錯的方法。作為 Apache APISIX 社區的一員,我一直都在社區里面“潛水”,看到了最近 Apache APISIX 在生態方面的持續進步,其實我也有些心動,一直在使用 Apache APISIX,但還沒有給社區貢獻過代碼,不如就借這個機會為社區的生態發展添一把火吧。
clickhouse-logger插件的作為一個中間層,對接 Apache APISIX 和 ClickHouse。如前文所說,我們使用Apache APISIX 作為七層負載均衡,請求經過 Apache APISIX 會產生日志,比如 access log 和 error log。clickhouse-logger
收集到日志后,會按照自身 metadata 所設置的日志格式,對這些日志進行整理。最后依靠批處理器將整理過的日志批量發送至 ClickHouse。
clickhouse-logger
在我們這個場景下,起到了替代“tcp-logger+rsyslog+Promtail+Loki”的作用。免除了多個組件之間的格式轉換和數據轉發,可將 Log 數據請求直接推送到 ClickHouse 服務器。
以下是在一個路由中啟用 clickhouse-logger
插件的示例過程。
運行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_addr | string | 是 | n/a | n/a | ClickHouse 服務器的 endpoint。 |
database | string | 是 | n/a | n/a | 使用的數據庫。 |
logtable | string | 是 | n/a | n/a | 寫入的表名 。 |
user | string | 是 | n/a | n/a | ClickHouse 的用戶。 |
password | string | 是 | n/a | ClickHouse 的密碼 。 | |
timeout | integer | 否 | 3 | [1,…] | 發送請求后保持連接活動的時間。 |
name | string | 否 | “clickhouse-logger” | n/a | 標識 logger 的唯一標識符。 |
batch_max_size | integer | 否 | 100 | [1,…] | 設置每批發送日志的最大條數,當日志條數達到設置的最大值時,會自動推送全部日志到 clickhouse 。 |
max_retry_count | integer | 否 | 0 | [0,…] | 從處理管道中移除之前的最大重試次數。 |
retry_delay | integer | 否 | 1 | [0,…] | 如果執行失敗,則應延遲執行流程的秒數。 |
ssl_verify | boolean | 否 | true | [true,false] | 驗證證書。 |
curl
命令測試插件。curl -i http://127.0.0.1:9080/hello
HTTP/1.1 200 OK
...
hello, world
你可以使用 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": {
"host": "$host",
"@timestamp": "$time_iso8601",
"client_ip": "$remote_addr"
}
}'
以 JSON 格式的鍵值對來聲明日志格式。對于值部分,僅支持字符串。如果是以 $
開頭,則表明是要獲取 APISIX 變量或 Nginx 內置變量。該設置是全局生效的,意味著指定 log_format
后,將對所有綁定 http-logger
的 Route 或 Service 生效。
CREATE TABLE default.test (
host
String,
client_ip
String,
route_id
String,
@timestamp
String,
PRIMARY KEY(@timestamp
)
) ENGINE = MergeTree()
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 │
└───────────┴───────────┴──────────┴───────────────────────────┘
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"
}
}
}'
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-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