storm-kafka-client 源码调试一

227 阅读2分钟

storm-kafka-client 源码调试一

前言

Storm-kafka-client 作为storm官方实现的kafka扩展包,为我们在使用 kafka 作为 storm 的数据源时提供了极大的便利。但其中结合 storm 框架实现的ack/fail机制,拉取等方法还是值得我们一看源码的。下面先着手准备一下源码的的调试环境。

环境准备

mac下,由于在jdk11环境中调试存在报错情况,所以 storm-kafka-client 调试环境最好为jdk1.8。

  1. 下载安装 jdk8,可通过官网下载,但需登陆,也可通过国内的相关镜像网站下载。下载完成后双击安装即可,安装后的 jdk 位于/Library/Java/JavaVirtualMachines/目录下。
  2. 配置环境变量
vi ~/.bash_profile
添加如下配置:
export JAVA_8_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home
export JAVA_11_HOME=/Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home
PATH=$JAVA_HOME/bin:$PATH CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar

export JAVA_HOME=$JAVA_8_HOME
export PATH
export CLASSPATH

alias jdk8="export JAVA_HOME=$JAVA_8_HOME"
alias jdk11="export JAVA_HOME=$JAVA_11_HOME"
保存后退出

source ~/.bash_profile,使配置文件生效。若为zsh终端,则需通过vi ~/.zshrc中添加source ~/.bash_profile,然后source ~/.zshrc使配置生效。

  1. 验证

image.png

此外还需要maven环境和kafka环境,此前发过相关环境配置,就不赘述了。

下载源码

storm 是apache的开源项目,作为扩展的storm-kafka-client自然也是开源的,可以通过 git clone git://github.com/apache/storm.git 或者直接通过git下载zip包。 完成上述步骤后,需要在项目的顶层目录执行mvn clean install -DskipTests=true,否则在idea编译项目时会报找不到 xxxxxx--SNAPSHOT错误。

调试源码

我们通过idea打开 /storm/external/ 下的 storm-kafka-client 项目,在 org.apache.storm.kafka 下新建包mytest。
在 mytest 下新建 MyTopology 类,用于提交测试的拓扑,包含 MyKafkaSpout 和 OutBolt 两个组件。

public class MyTopology {

    private static final String VERSION = "1.0";
    private static final String SPOUTID = "MyKafkaSpout-" + VERSION;
    private static final String OUTBOLT = "OutBolt- " + VERSION;

    public static void main(String[] args) {
        boolean local = true;
        LocalCluster cluster = null;
        Config topologyConfig = getMyTopologyConfig();
        TopologyBuilder topologyBuilder = new TopologyBuilder();
        getMyTopology(topologyBuilder);
        if(local) {
            try {
                cluster = new LocalCluster();
                cluster.submitTopology(MyTopology.class.getSimpleName(), topologyConfig, topologyBuilder.createTopology());
                Utils.sleep(600000);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                cluster.shutdown();
            }
        } else {
            try {
                StormSubmitter.submitTopologyWithProgressBar(MyTopology.class.getSimpleName(), topologyConfig, topologyBuilder.createTopology());
            } catch (AlreadyAliveException | InvalidTopologyException | AuthorizationException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * description: build topology
     * Params: TopologyBuilder topologyBuilder
     */
    private static void getMyTopology(TopologyBuilder topologyBuilder) {
        KafkaSpout kafkaSpout = new MyKafkaSpout().getKafkaSpout();
        topologyBuilder.setSpout(SPOUTID, kafkaSpout, 1);
        topologyBuilder.setBolt(OUTBOLT, new OutBolt(), 1).shuffleGrouping(SPOUTID);
    }

    /**
     * description: get the config of MyTopology
     * @return Config config
     */
    private static Config getMyTopologyConfig() {
        Config config = new Config();
        config.setNumAckers(1);
        config.setNumWorkers(1);
        config.setMessageTimeoutSecs(30);

        return config;
    }

}

新建 MyKafkaSpout 类,MyKafkaSpout 组件用于从 kafka 上拉取数据,调试 storm-kafka-client 源码。

public class MyKafkaSpout {
    public static final String MYBOOTSTRAPSERVER = "xxx.xxx.xxx.xxx:9092";
    public static final String MYTOPIC = "test";

    public KafkaSpout getKafkaSpout(){
        Map<String, Object> kafkaParams = getKafkaParams();
        KafkaSpoutConfig<String, String> kafkaConfig = KafkaSpoutConfig.builder(MYBOOTSTRAPSERVER, new String[] { MYTOPIC })
                .setFirstPollOffsetStrategy(KafkaSpoutConfig.FirstPollOffsetStrategy.EARLIEST).setProp(kafkaParams).build();

        return new KafkaSpout<>(kafkaConfig);
    }

    private Map<String, Object> getKafkaParams() {
        Map<String, Object> kafkaParams = new HashMap<>();
        kafkaParams.put("session.timeout.ms", "30000");
        kafkaParams.put("heartbeat.interval.ms", "10000");

        return kafkaParams;
    }
}

新建 OutBolt 类,OutBolt 组件主要用来输出从kafka 上获取的数据。

public class OutBolt extends BaseBasicBolt {

    @Override
    public void execute(Tuple tuple, BasicOutputCollector basicOutputCollector) {
        String msg = tuple.getStringByField("value");
        System.out.println(msg);
    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
        //this bolt emit nothing.
    }
}

至此,调试环境准备完毕,我们就可以通过debug的方式一步一步深入源码。简要源码分析,请听下回分解。

该博客仅为初学者自我学习的记录,粗浅之言,如有不对之处,恳请指正。