本文目录导读:

- 直接生成 YAML/JSON 配置文件(最常用)
- 使用模板引擎生成(适合动态配置)
- 生成 Java 代码文件(用于实际提交)
- 生成 Python 脚本直接提交拓扑(使用 pystorm)
- 最佳实践建议
- 关键建议:
Python 生成 Storm 拓扑配置通常有以下几种方式,根据你的实际场景选择最合适的方法:
直接生成 YAML/JSON 配置文件(最常用)
import yaml
import json
def generate_storm_topology_yaml():
config = {
"name": "my-storm-topology",
"spouts": [
{
"id": "kafka-spout",
"className": "org.apache.storm.kafka.KafkaSpout",
"parallelism": 3,
"config": {
"kafka.bootstrap.servers": "localhost:9092",
"kafka.topic": "input-topic",
"kafka.group.id": "storm-consumer"
}
}
],
"bolts": [
{
"id": "filter-bolt",
"className": "com.example.FilterBolt",
"parallelism": 5,
"config": {
"filter.field": "status",
"filter.value": "active"
}
},
{
"id": "output-bolt",
"className": "com.example.OutputBolt",
"parallelism": 2
}
],
"connections": [
{"from": "kafka-spout", "to": "filter-bolt", "grouping": "shuffle"},
{"from": "filter-bolt", "to": "output-bolt", "grouping": "fields", "fields": ["user_id"]}
],
"config": {
"topology.workers": 3,
"topology.max.spout.pending": 1000,
"topology.message.timeout.secs": 300
}
}
# 生成 YAML
with open('topology.yaml', 'w') as f:
yaml.dump(config, f, default_flow_style=False)
# 生成 JSON
with open('topology.json', 'w') as f:
json.dump(config, f, indent=2)
return config
# 生成配置
topology_config = generate_storm_topology_yaml()
使用模板引擎生成(适合动态配置)
from jinja2 import Template
def generate_storm_config_with_template(spout_configs, bolt_configs, env="production"):
# Jinja2 模板
template_str = """
name: {{ topology_name }}
spouts:
{% for spout in spouts %}
- id: {{ spout.id }}
className: {{ spout.class_name }}
parallelism: {{ spout.parallelism }}
config:
{% for key, value in spout.config.items() %}
{{ key }}: {{ value }}
{% endfor %}
{% endfor %}
bolts:
{% for bolt in bolts %}
- id: {{ bolt.id }}
className: {{ bolt.class_name }}
parallelism: {{ bolt.parallelism }}
config:
{% for key, value in bolt.config.items() %}
{{ key }}: {{ value }}
{% endfor %}
{% endfor %}
connections:
{% for conn in connections %}
- from: {{ conn.from_id }}
to: {{ conn.to_id }}
grouping: {{ conn.grouping }}
{% if conn.fields %}
fields: {{ conn.fields }}
{% endif %}
{% endfor %}
config:
topology.workers: {{ workers }}
topology.max.spout.pending: {{ max_pending }}
topology.message.timeout.secs: {{ timeout }}
env: {{ environment }}
"""
template = Template(template_str)
# 环境特定配置
env_configs = {
"development": {"workers": 1, "max_pending": 100, "timeout": 30},
"staging": {"workers": 3, "max_pending": 500, "timeout": 120},
"production": {"workers": 10, "max_pending": 5000, "timeout": 300}
}
config = env_configs[env]
config.update({
"topology_name": "my-topology",
"spouts": spout_configs,
"bolts": bolt_configs,
"connections": generate_connections(spout_configs, bolt_configs),
"environment": env
})
return template.render(**config)
def generate_connections(spouts, bolts):
connections = []
# 自动生成连接逻辑
for spout in spouts:
for bolt in bolts:
if bolt.input_type == spout.output_type:
connections.append({
"from_id": spout.id,
"to_id": bolt.id,
"grouping": "shuffle"
})
return connections
# 使用示例
spouts = [
{
"id": "kafka-spout",
"class_name": "org.apache.storm.kafka.KafkaSpout",
"parallelism": 3,
"config": {"topic": "input", "bootstrap.servers": "localhost:9092"},
"output_type": "raw_data"
}
]
bolts = [
{
"id": "filter-bolt",
"class_name": "com.example.FilterBolt",
"parallelism": 5,
"config": {"threshold": 100},
"input_type": "raw_data"
}
]
config = generate_storm_config_with_template(spouts, bolts, "production")
with open('topology_generated.yaml', 'w') as f:
f.write(config)
生成 Java 代码文件(用于实际提交)
def generate_storm_java_topology(topology_name, spouts, bolts):
java_code = f"""
import org.apache.storm.Config;
import org.apache.storm.LocalCluster;
import org.apache.storm.StormSubmitter;
import org.apache.storm.topology.TopologyBuilder;
import org.apache.storm.kafka.spout.KafkaSpout;
public class {topology_name}Topology {{
public static void main(String[] args) throws Exception {{
TopologyBuilder builder = new TopologyBuilder();
// 设置 Spouts
"""
# 添加 Spout 代码
for spout in spouts:
java_code += f"""
builder.setSpout("{spout['id']}",
new {spout['class_name']}({spout.get('config_params', '')}),
{spout['parallelism']});
"""
# 添加 Bolt 代码
java_code += "\n // 设置 Bolts\n"
for bolt in bolts:
java_code += f"""
builder.setBolt("{bolt['id']}",
new {bolt['class_name']}({bolt.get('config_params', '')}),
{bolt['parallelism']})
.{bolt['grouping']}("{bolt['from_spout']}");
"""
# 添加配置
java_code += f"""
Config config = new Config();
config.setDebug(false);
config.setNumWorkers({workers_count});
if (args != null && args.length > 0) {{
StormSubmitter.submitTopology(args[0], config, builder.createTopology());
}} else {{
LocalCluster cluster = new LocalCluster();
cluster.submitTopology("{topology_name}", config, builder.createTopology());
Thread.sleep(10000);
cluster.shutdown();
}}
}}
}}
"""
return java_code
# 使用示例
spouts = [
{
"id": "kafka-spout",
"class_name": "org.apache.storm.kafka.spout.KafkaSpout",
"parallelism": 3,
"config_params": "KafkaSpoutConfig.builder(\"localhost:9092\", \"topic\").build()",
"grouping": "shuffle",
"output_field": "value"
}
]
bolts = [
{
"id": "filter-bolt",
"class_name": "com.example.FilterBolt",
"parallelism": 2,
"grouping": "shuffle",
"from_spout": "kafka-spout"
}
]
workers_count = 3
java_code = generate_storm_java_topology("MyStormTopology", spouts, bolts)
with open('MyStormTopology.java', 'w') as f:
f.write(java_code)
生成 Python 脚本直接提交拓扑(使用 pystorm)
import subprocess
import json
def generate_storm_submit_script(topology_name, jar_path, config):
# 生成提交命令
storm_cmd = f"""
storm jar {jar_path} org.apache.storm.flux.Flux \\
--local \\ # 或 --remote 提交到集群
--sleep 5000 \\
-R yaml \\
-filter '{{
"name": "{topology_name}",
"config": {json.dumps(config)}
}}'
"""
# 或者生成 Flux YAML 配置
flux_config = {
"name": topology_name,
"config": config,
"components": [],
"spouts": [
{
"id": "kafka-spout",
"className": "org.apache.storm.kafka.spout.KafkaSpout",
"constructorArgs": [
{"type": "string", "value": "localhost:9092"},
{"type": "string", "value": "input-topic"}
]
}
],
"bolts": [
{
"id": "process-bolt",
"className": "com.example.ProcessBolt",
"parallelism": 2,
"constructorArgs": [
{"type": "string", "value": "param1"}
]
}
],
"streams": [
{
"from": "kafka-spout",
"to": "process-bolt",
"grouping": {
"type": "SHUFFLE"
}
}
]
}
with open(f'flux_{topology_name}.yaml', 'w') as f:
yaml.dump(flux_config, f)
return storm_cmd
# 使用示例
config = {
"topology.workers": 3,
"topology.max.spout.pending": 5000,
"topology.debug": False
}
submit_script = generate_storm_submit_script(
"my-topology",
"/path/to/storm-starter-1.2.3.jar",
config
)
# 保存脚本
with open('submit_topology.sh', 'w') as f:
f.write("#!/bin/bash\n")
f.write(submit_script)
最佳实践建议
# 配置文件生成器类
class StormConfigGenerator:
def __init__(self, topology_name, environment="development"):
self.topology_name = topology_name
self.environment = environment
self.config = {
"spouts": [],
"bolts": [],
"streams": [],
"components": [],
"config": self._get_base_config()
}
def _get_base_config(self):
base_config = {
"topology.workers": 3,
"topology.max.spout.pending": 1000,
"topology.message.timeout.secs": 300
}
if self.environment == "production":
base_config.update({
"topology.workers": 10,
"topology.max.spout.pending": 50000,
"topology.debug": False
})
elif self.environment == "development":
base_config.update({
"topology.workers": 1,
"topology.max.spout.pending": 10,
"topology.debug": True
})
return base_config
def add_spout(self, spout_id, class_name, parallelism=1, **kwargs):
self.config["spouts"].append({
"id": spout_id,
"className": class_name,
"parallelism": parallelism,
**kwargs
})
def add_bolt(self, bolt_id, class_name, parallelism=1, **kwargs):
self.config["bolts"].append({
"id": bolt_id,
"className": class_name,
"parallelism": parallelism,
**kwargs
})
def add_stream(self, from_id, to_id, grouping="SHUFFLE", **kwargs):
self.config["streams"].append({
"from": from_id,
"to": to_id,
"grouping": {"type": grouping},
**kwargs
})
def save(self, filename=None):
if not filename:
filename = f"topology_{self.topology_name}_{self.environment}.yaml"
with open(filename, 'w') as f:
yaml.dump(self.config, f, default_flow_style=False)
print(f"Configuration saved to {filename}")
return self.config
# 使用示例
generator = StormConfigGenerator(
topology_name="data-pipeline",
environment="production"
)
generator.add_spout(
"kafka-spout",
"org.apache.storm.kafka.spout.KafkaSpout",
parallelism=3,
constructorArgs=[
{"type": "string", "value": "localhost:9092"},
{"type": "string", "value": "data-topic"}
]
)
generator.add_bolt(
"filter-bolt",
"com.example.DataFilterBolt",
parallelism=5,
constructorArgs=[
{"type": "int", "value": 100}
]
)
generator.add_bolt(
"output-bolt",
"com.example.OutputBolt",
parallelism=2
)
generator.add_stream("kafka-spout", "filter-bolt", "SHUFFLE")
generator.add_stream("filter-bolt", "output-bolt", "FIELDS",
fields=["user_id"])
# 生成配置文件
config = generator.save()
关键建议:
- 使用 YAML:Storm Flux 原生支持 YAML,是最推荐的方式
- 环境分离:开发/测试/生产环境配置分开管理
- 版本控制:配置文件纳入 Git 管理
- 参数化:使用模板生成动态配置
- 验证:生成配置后做基础验证(检查连接完整性等)
选择哪种方式取决于你的部署流程和团队技术栈,YAML + Storm Flux 是官方推荐的主流方式。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播