距離上次 APISIX v2.13 LTS 版本釋出已經有兩個多月的時間,以往每次 APISIX 的小版本釋出,都會為大家帶來新功能。然而 APISIX v2.14.1 版本釋出的功能,將緊跟技術前沿,為大家帶來了諸多探索性的新功能,併為 APISIX v3 版本的釋出投石問路,歡迎大家探索這些新功能。
接下來我們先看下 APISIX 支援了哪些探索性的新功能。
基於 WebSocket 的 pubsub 代理框架
在 APISIX v2.14.1 版本之前,無論是代理 gRPC 請求還是普通的 HTTP 請求,APISIX 的上游都是對接的應用伺服器,無法滿足多元化場景需求。例如使用者需要使用其他上游型別(比如 Kafka),就只能通過其他方式實現。但是在 APISIX v2.14.1 版本中,APISIX 新增了一個基於 Websocket 的訊息訂閱代理框架,該框架允許客戶端通過 APISIX 來訂閱指定訊息佇列(上游)中的訊息。現在你可以使用 APISIX來訂閱 Kafka 中的訊息。
以 Kafka 為例,我們需要如下配置:
curl -X PUT 'http://127.0.0.1:9080/apisix/admin/routes/kafka' \
-H 'X-API-KEY: ${api-key}' \
-H 'Content-Type: application/json' \
-d '{
"uri": "/kafka",
"upstream": {
"nodes": {
"kafka-server1:9092": 1,
"kafka-server2:9092": 1,
"kafka-server3:9092": 1
},
"type": "none",
"scheme": "kafka"
}
}'
上述示例是在路由中新增了一個 Kafka 型別的上游,幷包含了多個 Broker。
你可以參考以下步驟訂閱該上游:
- 首先請通過 WebSocket 建立連線。
- 獲取 Topic 中的某個 Partition 當前的 offset。以下示例使用了 Protobuf 來編碼相關的請求和響應:
message PubSubReq {
int64 sequence = 1;
oneof req {
CmdEmpty cmd_empty = 31;
CmdPing cmd_ping = 32;
CmdKafkaFetch cmd_kafka_fetch = 33;
CmdKafkaListOffset cmd_kafka_list_offset = 34;
};
}
message PubSubResp {
int64 sequence = 1;
oneof resp {
ErrorResp error_resp = 31;
PongResp pong_resp = 32;
KafkaFetchResp kafka_fetch_resp = 33;
KafkaListOffsetResp kafka_list_offset_resp = 34;
};
}
比如獲取 offset 的請求就是:
message CmdKafkaListOffset {
string topic = 1;
int32 partition = 2;
int64 timestamp = 3;
}
各個欄位具體含義請參考 pubsub.proto。
- 之後每次訂閱操作都可以根據當前的 offset 來獲取最新的訊息。
注意:成功獲取訊息之後,需要更新當前的 offset,更新後的 offset 是之前返回的 offset + 1。
具體操作可參考原始碼和測試用例:
雖然當前的 Pubsub 框架僅提供了底層的介面,但是它已經實現了兩個最基本的需求:
- 通過常用的
80/443
埠暴露 Kafka 服務能力,無需應用伺服器再封裝多一層。 - 允許新增鑑權外掛,像使用一般的 Websocket 框架那樣給 Kafka 的服務增加安全保護。
如果你在實際使用過程中遇到問題,可以通過提交 issue 的方式反饋給 Apache APISIX 社群,社群將根據使用者的反饋,繼續完善和增強這一功能。
基於 xRPC 框架管理非 HTTP 的 7 層協議
APISIX 在早期版本就支援代理 TCP 協議,但是部分場景中,純粹的 TCP 協議代理無法滿足使用者需求。因為有些功能必須在對應用協議進行編解碼之後才能實現,因此使用者就需要特定應用協議的代理,比如 Redis Proxy、Kafka Proxy 等。
從 APISIX v2.14.1 版本開始,APISIX 提供了 xRPC 框架,允許開發者在該框架上自定義特定的應用協議。基於 xRPC 框架,APISIX 可以提供對若干主流應用協議的代理支援。同時使用者也可以基於該框架來支援自己私有的基於 TCP 的應用協議,使其具備類似 HTTP 協議代理的精準顆粒度和更高階的 7 層控制。
目前,APISIX 已經在 xRPC 框架上實現了 Redis 的代理功能,支援了根據命令注入延遲和有選擇性地記錄日誌內容。儘管 APISIX 需要對 Redis 協議進行編解碼,但是在簡單的 SET/GET 效能測試中,使用雙 Worker 程式的 APISIX 進行代理,其效能可以達到直連 Redis 的 80%。
你可以參考以下命令建立一個代理 Redis 協議的流路由:
curl http://127.0.0.1:9080/apisix/admin/stream_routes/1 \
-H 'X-API-KEY: ${api-key}' -X PUT -d '
{
"upstream": {
"type": "none",
"nodes": {
"127.0.0.1:6379": 1
}
},
"protocol": {
"name": "redis",
"conf": {
"faults": [{
"commands": ["get", "ping"],
"delay": 5
}]
},
logger = {
[
"name": "syslog",
"filter": [
["rpc_time", ">=", 1],
],
"conf": {
"host": "127.0.0.1",
"port": 8125,
"sock_type": "udp",
"batch_max_size": 1,
"flush_limit": 1
}
]
}
}
}'
以上配置釋義如下:
當命令是 GET 或 ping 時,將會有 5 秒延遲。同時每個命令執行之後,會判斷其花費的時間是否超過 1 秒,如果是,則觸發對應的 logger
物件,併傳送 syslog
UDP 日誌到 127.0.0.1
的 8125
埠。
控制面支援服務發現
在 v2.14.1 版本之前,APISIX 僅在資料面支援了服務發現。這種情況下,每個 APISIX 例項都需要獲取服務發現的資料,但是使用者在實際應用過程中,反饋了以下問題:
- 每個 APISIX 例項都需要從服務發現系統里拉取資料,這讓網路拓撲變得複雜。
- 服務發現配置需要在每個 APISIX 例項都配置一遍。如需修改密碼,就必須修改配置檔案,然後釋出到每個 APISIX 例項上。
- 當前許多服務發現都沒有提供 Lua SDK,如果要使用這些服務發現系統,就需要自己直接對接該伺服器提供的 HTTP API (假如存在)。
因此從 v2.14.1 版本開始,APISIX 將在控制面支援服務發現功能。服務發現將通過 APISIX-Seed 實現。
該功能實現原理是通過 apisix-seed
同時監聽 etcd 中 Upstream 相關的資源和服務發現元件中對應的上游服務資源,當服務發現元件中的上游服務資源發生變化時更新 etcd 中相關的 Upstream 資訊。
具體實現流程如下圖:
目前來看,控制面服務發現的方案也有不足之處,比如對 etcd 的壓力較大。因此 APISIX 會同時保留兩種服務發現方案,並通過更多實際應用來證明哪個方案會更優。
初步支援 Istio
為了適應更廣泛的應用場景,從 v2.14.1 版本開始,APISIX 將嘗試相容 Istio,以 Istio 為控制面、APISIX 為資料面的形式,開始在服務網格領域中探索。
由於 Istio 的配置是通過 xDS 協議下發的,所以開發了 Amesh 專案,把 Istio 下發的 xDS 轉換成 APISIX 的配置。目前,APISIX 已經能夠跑通 Istio 官方的 Simple Bookstore App demo。在後續版本中,APISIX 也會繼續拓寬對 xDS 的支援,把 Istio 和 APISIX 的能力越來越緊密地結合在一起。
更多外掛和功能
除了上面提到的幾個探索性功能外,本次版本釋出也為使用者提供了一些較為傳統的功能:
- 新增
casdoor
外掛,提高與 Casdoor 的互動體驗。 response-rewrite
外掛增加了針對 Body 的替換過濾器。
更多功能更新和 Bug 修復細節,請檢視官方 Releases CHANGELOG。