Skip to content

Commit b7e67ae

Browse files
authored
feat: add kafka connection (#4036)
## Summary Add Kafka named connection support and allow Kafka sink configs to reuse broker connection settings through `connectionSelector`. ## Changes - Added a stateless Kafka connection implementation. - Parses Kafka broker, TLS, and SASL settings. - Uses `kafka-go` dial as the health check. - Does not hold producer, consumer, or long-lived Kafka network resources. - Registers the `kafka` connection provider when the Kafka implementation package is loaded. - Updated Kafka sink metadata. - Added `connectionSelector`. - Marked Kafka broker, SASL, and TLS-related fields as connection-related. - Added test coverage. - Unit coverage for Kafka connection provisioning and registration. - Config merge coverage for Kafka sink `connectionSelector`. - FVT coverage for `memory source -> Kafka sink` using a Kafka named connection. - Added Kafka FVT as a standalone test job in the main test workflow. - Starts Redpanda locally. - Creates a Kafka named connection. - Creates a Kafka sink rule using only `connectionSelector + topic`. - Verifies the message is written to Kafka. ## Verification - `go test ./extensions/impl/kafka -run 'TestKafkaConnection'` - `go test ./internal/topo/node/conf -run TestOverwriteKafkaConnectionProps` - `go test -trimpath -tags='full deadlock' -count=1 -v ./fvt -run TestKafkaConnectionSelectorSinkE2E` - `go test -tags full ./internal/binder/io` - `python3 -m json.tool extensions/sinks/kafka/kafka.json` Note: The final workflow-only adjustment was pushed without rerunning local tests per maintainer request. --------- Signed-off-by: Song Gao <disxiaofei@163.com>
1 parent a89572c commit b7e67ae

12 files changed

Lines changed: 622 additions & 11 deletions

File tree

.github/workflows/run_test_case.yaml

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,72 @@ jobs:
128128
run_fvt_tests:
129129
uses: ./.github/workflows/run_fvt_tests.yaml
130130

131+
run_kafka_fvt_tests:
132+
name: Run Kafka fvt tests
133+
runs-on: ubuntu-latest
134+
timeout-minutes: 15
135+
env:
136+
DEBIAN_FRONTEND: noninteractive
137+
steps:
138+
- uses: actions/checkout@v4
139+
- uses: actions/setup-go@v5
140+
with:
141+
go-version: '1.25.4'
142+
- name: Install dependencies
143+
run: |
144+
sudo apt-get update
145+
sudo apt-get install -y ffmpeg libzmq3-dev pkg-config
146+
- name: Prepare eKuiper runtime directories
147+
run: |
148+
mkdir -p data log plugins/sources plugins/sinks plugins/functions
149+
- name: Start Redpanda
150+
run: |
151+
docker run -d --name redpanda \
152+
-p 9092:9092 \
153+
docker.redpanda.com/redpandadata/redpanda:v24.3.6 \
154+
redpanda start \
155+
--overprovisioned \
156+
--smp 1 \
157+
--memory 512M \
158+
--reserve-memory 0M \
159+
--node-id 0 \
160+
--check=false \
161+
--kafka-addr PLAINTEXT://0.0.0.0:9092 \
162+
--advertise-kafka-addr PLAINTEXT://127.0.0.1:9092 \
163+
--set redpanda.auto_create_topics_enabled=true
164+
- name: Wait for Redpanda
165+
run: |
166+
for i in {1..60}; do
167+
if docker exec redpanda rpk cluster info >/dev/null 2>&1; then
168+
exit 0
169+
fi
170+
sleep 1
171+
done
172+
docker logs redpanda
173+
exit 1
174+
- name: Run Kafka connection selector FVT
175+
env:
176+
FVT_KAFKA_BROKER: 127.0.0.1:9092
177+
KUIPER__BASIC__ALLOWEXTERNALFILEACCESS: "true"
178+
run: |
179+
go test -trimpath -race -tags="full deadlock" -count=1 -v ./fvt -run TestKafkaConnectionSelectorSinkE2E
180+
- uses: actions/upload-artifact@v4
181+
if: failure()
182+
with:
183+
name: kafka_fvt_stream_log
184+
path: log/stream.log
185+
- name: Dump Redpanda logs
186+
if: failure()
187+
run: docker logs redpanda
188+
- name: Stop Redpanda
189+
if: always()
190+
run: docker rm -f redpanda
191+
131192
upload_coverage:
132193
needs:
133194
- run_unit_tests
134195
- run_fvt_tests
196+
- run_kafka_fvt_tests
135197
runs-on: ubuntu-latest
136198
steps:
137199
- name: Download ut coverage reports
@@ -161,4 +223,4 @@ jobs:
161223
token: ${{ secrets.CODECOV_TOKEN }}
162224
fail_ci_if_error: false
163225
version: v10.2.1
164-
verbose: true
226+
verbose: true

docs/en_US/api/restapi/connection.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Source/Sink in rules can be created and managed independently in the form of con
66

77
### Create connection
88

9-
To create a connection, provide the connection's id, type, and configuration parameters. Currently, `mqtt`/`nng`/`httppush`/`websocket`/`edgex`/`sql` type connections are supported. Here we take creating an mqtt connection as an example.
9+
To create a connection, provide the connection's id, type, and configuration parameters. Currently, `mqtt`/`nng`/`httppush`/`websocket`/`edgex`/`sql`/`kafka` type connections are supported. Here we take creating an mqtt connection as an example.
1010

1111
```shell
1212
POST http://localhost:9081/connections
@@ -19,9 +19,23 @@ POST http://localhost:9081/connections
1919
}
2020
```
2121

22+
To create a Kafka connection, use `kafka` as the connection type and provide the Kafka connection properties in `props`.
23+
24+
```shell
25+
POST http://localhost:9081/connections
26+
{
27+
"id": "kafka-1",
28+
"typ": "kafka",
29+
"props": {
30+
"brokers": "127.0.0.1:9092",
31+
"saslAuthType": "none"
32+
}
33+
}
34+
```
35+
2236
### Update connection
2337

24-
To update a connection, provide the connection's id, type, and configuration parameters. Currently, `mqtt`/`nng`/`httppush`/`websocket`/`edgex`/`sql` types of connections are supported. Here we take updating the mqtt connection as an example. If the connection is referenced by a rule, it cannot be updated.
38+
To update a connection, provide the connection's id, type, and configuration parameters. Currently, `mqtt`/`nng`/`httppush`/`websocket`/`edgex`/`sql`/`kafka` types of connections are supported. Here we take updating the mqtt connection as an example. If the connection is referenced by a rule, it cannot be updated.
2539

2640
```shell
2741
PUT http://localhost:9081/connections/connection-1

docs/en_US/guide/connections/overview.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ eKuiper v2 introduced an internal connection pool component and adapted a series
1717
- SQL Connection
1818
- HTTP Connection (including REST sink, HTTP Pull source, and HTTP push source connections)
1919
- WebSocket Connection
20+
- Kafka Connection
2021

2122
Other connection types may be gradually integrated in subsequent versions. Connection types integrated into the
2223
connection pool can be independently created via API and accessed.
@@ -89,7 +90,7 @@ demo_conf: #Conf_key
8990
#Override the global configurations
9091
demo2_conf: #Conf_key
9192
qos: 0
92-
connentionSelector: mqttcon1
93+
connectionSelector: mqttcon1
9394
servers: [ tcp://10.211.55.6:1883, tcp://127.0.0.1 ]
9495
```
9596

@@ -118,7 +119,12 @@ will trigger the subscription.
118119

119120
:::
120121

121-
You can also reuse the defined connection resource in the rule's action via `connentionSelector`.
122+
You can also reuse the defined connection resource in the rule's action via `connectionSelector`.
123+
124+
For Kafka sinks, `connectionSelector` can be used to reuse a Kafka connection resource. The Kafka connection is used to
125+
manage connection status and verify broker connectivity by pinging the configured brokers. When a Kafka sink references
126+
the connection, connection-related properties such as `brokers`, SASL, and TLS settings are copied from the selected
127+
connection. The sink still creates its own Kafka producer for publishing messages.
122128
123129
## Connection Status
124130

docs/en_US/guide/sinks/plugin/kafka.md

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ Restart the eKuiper server to activate the plugin.
5656

5757
| Property name | Optional | Description |
5858
|--------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
59-
| brokers | false | The broker address list ,split with "," |
59+
| connectionSelector | true | Reuse the selected Kafka connection. When this property is set, Kafka connection-related properties such as `brokers`, SASL, and TLS settings are copied from the selected connection. |
60+
| brokers | true | The broker address list, split with ",". Required when `connectionSelector` is not set. |
6061
| topic | false | The topic of the Kafka |
6162
| saslAuthType | false | The Kafka sasl authType, support none,plain,scram |
6263
| saslUserName | true | The sasl user name |
@@ -77,6 +78,46 @@ Restart the eKuiper server to activate the plugin.
7778

7879
You can check the connectivity of the corresponding sink endpoint in advance through the API: [Connectivity Check](../../../api/restapi/connection.md#connectivity-check)
7980

81+
### Connection Reuse
82+
83+
You can create a Kafka connection and reuse its connection-related properties in Kafka sinks through
84+
`connectionSelector`. The Kafka connection is used to ping the configured brokers and manage connection status. The
85+
Kafka sink copies the selected connection's configuration and creates its own Kafka producer for publishing messages.
86+
87+
Create a Kafka connection:
88+
89+
```shell
90+
POST http://localhost:9081/connections
91+
{
92+
"id": "kafka-1",
93+
"typ": "kafka",
94+
"props": {
95+
"brokers": "127.0.0.1:9092",
96+
"saslAuthType": "none"
97+
}
98+
}
99+
```
100+
101+
Use the connection in a Kafka sink:
102+
103+
```json
104+
{
105+
"id": "kafka",
106+
"sql": "SELECT * FROM demo_stream",
107+
"actions": [
108+
{
109+
"kafka": {
110+
"connectionSelector": "kafka-1",
111+
"topic": "test_topic"
112+
}
113+
}
114+
]
115+
}
116+
```
117+
118+
When `connectionSelector` is set, the sink ignores connection-related properties configured directly in the sink action,
119+
including `brokers`, `saslAuthType`, `saslUserName`, `password`, `insecureSkipVerify`, and TLS certificate properties.
120+
80121
### Setting Kafka Key and Headers
81122

82123
Set the metadata when the Kafka client sends messages through keys and headers:

docs/zh_CN/api/restapi/connection.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
### 创建连接
88

9-
创建连接去要提供连接的 id, 类型和配置参数。目前已经支持了 `mqtt`/`nng`/`httppush`/`websocket`/`edgex`/`sql` 类型的连接,这里以创建 mqtt 连接为例。
9+
创建连接需要提供连接的 id类型和配置参数。目前已经支持了 `mqtt`/`nng`/`httppush`/`websocket`/`edgex`/`sql`/`kafka` 类型的连接,这里以创建 mqtt 连接为例。
1010

1111
```shell
1212
POST http://localhost:9081/connections
@@ -19,9 +19,23 @@ POST http://localhost:9081/connections
1919
}
2020
```
2121

22+
创建 Kafka 连接时,将连接类型设置为 `kafka`,并在 `props` 中提供 Kafka 连接配置。
23+
24+
```shell
25+
POST http://localhost:9081/connections
26+
{
27+
"id": "kafka-1",
28+
"typ": "kafka",
29+
"props": {
30+
"brokers": "127.0.0.1:9092",
31+
"saslAuthType": "none"
32+
}
33+
}
34+
```
35+
2236
### 更新连接
2337

24-
更新连接要提供连接的 id, 类型和配置参数。目前已经支持了 `mqtt`/`nng`/`httppush`/`websocket`/`edgex`/`sql` 类型的连接,这里以更新 mqtt 连接为例。如果连接被规则引用中,则无法被更新。
38+
更新连接要提供连接的 id类型和配置参数。目前已经支持了 `mqtt`/`nng`/`httppush`/`websocket`/`edgex`/`sql`/`kafka` 类型的连接,这里以更新 mqtt 连接为例。如果连接被规则引用中,则无法被更新。
2539

2640
```shell
2741
PUT http://localhost:9081/connections/connection-1

docs/zh_CN/guide/connections/overview.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ v2 增加了内部的连接池组件,并适配了一系列连接类型:
1414
- SQL 连接
1515
- HTTP 连接 (包括 REST sink,HTTP Pull source,HTTP push source 使用的连接)
1616
- WebSocket 连接
17+
- Kafka 连接
1718

1819
其余连接类型可能会在后续版本中陆续接入。接入连接池的连接类型可通过 API 进行资源的独立创建,并获取 API。
1920

@@ -73,7 +74,7 @@ demo_conf: #Conf_key
7374
#Override the global configurations
7475
demo2_conf: #Conf_key
7576
qos: 0
76-
connentionSelector: mqttcon1
77+
connectionSelector: mqttcon1
7778
servers: [ tcp://10.211.55.6:1883, tcp://127.0.0.1 ]
7879
```
7980

@@ -99,7 +100,11 @@ demo2 (
99100

100101
:::
101102

102-
也可以在规则的 action 中,通过 connentionSelector 重用定义的连接资源。
103+
也可以在规则的 action 中,通过 `connectionSelector` 重用定义的连接资源。
104+
105+
对于 Kafka sink,可以通过 `connectionSelector` 重用 Kafka 连接资源。Kafka 连接用于管理连接状态,并通过 ping 配置的 broker
106+
来验证连通性。当 Kafka sink 引用该连接时,`brokers`、SASL、TLS 等连接相关配置会从选中的连接中复制。sink 仍会创建自己的 Kafka
107+
producer 用于发送消息。
103108

104109
## 连接状态
105110

docs/zh_CN/guide/sinks/plugin/kafka.md

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ $(PLUGINS_CUSTOM):
5656

5757
| 属性名称 | 是否可选 | 说明 |
5858
|--------------------|------|-------------------------------------------------------------------------------|
59-
| brokers || broker地址列表 ,用 "," 分割 |
59+
| connectionSelector || 重用选中的 Kafka 连接。设置该参数后,`brokers`、SASL、TLS 等 Kafka 连接相关配置会从选中的连接中复制。 |
60+
| brokers || broker 地址列表,用 "," 分割。未设置 `connectionSelector` 时必填。 |
6061
| topic || kafka 主题 |
6162
| saslAuthType || sasl 认证类型 , 支持none,plain,scram |
6263
| saslUserName || sasl 用户名 |
@@ -79,6 +80,45 @@ $(PLUGINS_CUSTOM):
7980

8081
你可以通过 api 的方式提前检查对应 sink 端点的连通性: [连通性检查](../../../api/restapi/connection.md#连通性检查)
8182

83+
### 连接重用
84+
85+
可以创建 Kafka 连接,并在 Kafka sink 中通过 `connectionSelector` 重用其中的连接相关配置。Kafka 连接会 ping 配置的 broker
86+
并管理连接状态。Kafka sink 会复制选中连接的配置,并创建自己的 Kafka producer 用于发送消息。
87+
88+
创建 Kafka 连接:
89+
90+
```shell
91+
POST http://localhost:9081/connections
92+
{
93+
"id": "kafka-1",
94+
"typ": "kafka",
95+
"props": {
96+
"brokers": "127.0.0.1:9092",
97+
"saslAuthType": "none"
98+
}
99+
}
100+
```
101+
102+
在 Kafka sink 中使用该连接:
103+
104+
```json
105+
{
106+
"id": "kafka",
107+
"sql": "SELECT * FROM demo_stream",
108+
"actions": [
109+
{
110+
"kafka": {
111+
"connectionSelector": "kafka-1",
112+
"topic": "test_topic"
113+
}
114+
}
115+
]
116+
}
117+
```
118+
119+
设置 `connectionSelector` 后,sink action 中直接配置的连接相关参数会被忽略,包括 `brokers``saslAuthType``saslUserName``password``insecureSkipVerify`
120+
以及 TLS 证书相关参数。
121+
82122
### 设置 key 和 headers
83123

84124
通过 key 和 headers 设置 Kafka 客户端发送消息时的元数据:

0 commit comments

Comments
 (0)