KafkaSpout(空闲)会产生巨大的网络流量

时间:2016-08-18 17:29:58

标签: apache-kafka apache-storm

在使用KafkaSpout和几个Bolts开发和执行我的Storm(1.0.1)拓扑之后,我注意到即使拓扑处于空闲状态时网络流量也很大(Kafka上没有消息,没有在螺栓中进行处理)。所以我开始逐个评论我的拓扑结构以找到原因,现在我的主要部分只有KafkaSpout:

....
final SpoutConfig spoutConfig = new SpoutConfig(
                new ZkHosts(zkHosts, "/brokers"), 
                "files-topic", // topic
                "/kafka", // ZK chroot 
                "consumer-group-name");
     spoutConfig.scheme = new SchemeAsMultiScheme(new StringScheme());
     spoutConfig.startOffsetTime = OffsetRequest.LatestTime();
     topologyBuilder.setSpout(
                        "kafka-spout-id, 
                        new KafkaSpout(config),
                        1); 
....

当这个(无用的)拓扑执行时,即使在本地模式下,即使是第一次,网络流量总是会增长很多:我看到(在我的活动监视器中)

  • 平均每秒收到432 KB的数据
  • 几个小时后拓扑正在运行(空闲)收到的数据是1.26GB,发送的数据是1GB

enter image description here

(重要:Kafka没有在集群中运行,一个单个实例在同一台机器上运行,只有一个主题和一个分区。我刚刚在我的机器上下载了Kafka,启动它并创建了一个简单的主题。当我把它放入主题中的消息,拓扑中的所有内容都没有任何问题。

显然,原因在于KafkaSpout.nextTuple()方法(下方),但我不明白为什么,在Kafka没有任何消息的情况下,我应该有这样的流量。有没有我没有考虑过的事情?这是预期的行为吗?我看看Kafka日志,ZK日志,什么都没有,我已经清理了Kafka和ZK数据,没有,仍然是相同的行为。

@Override
public void nextTuple() {
    List<PartitionManager> managers = _coordinator.getMyManagedPartitions();
    for (int i = 0; i < managers.size(); i++) {

        try {
            // in case the number of managers decreased
            _currPartitionIndex = _currPartitionIndex % managers.size();
            EmitState state = managers.get(_currPartitionIndex).next(_collector);
            if (state != EmitState.EMITTED_MORE_LEFT) {
                _currPartitionIndex = (_currPartitionIndex + 1) % managers.size();
            }
            if (state != EmitState.NO_EMITTED) {
                break;
            }
        } catch (FailedFetchException e) {
            LOG.warn("Fetch failed", e);
            _coordinator.refresh();
        }
    }

    long diffWithNow = System.currentTimeMillis() - _lastUpdateMs;

    /*
         As far as the System.currentTimeMillis() is dependent on System clock,
         additional check on negative value of diffWithNow in case of external changes.
     */
    if (diffWithNow > _spoutConfig.stateUpdateIntervalMs || diffWithNow < 0) {
        commit();
    }
}

2 个答案:

答案 0 :(得分:1)

  

在nextTuple()方法中休眠一秒钟(1000毫秒)并立即观察流量,例如,

@Override
public void nextTuple() {
   try {
       Thread.sleep(1000);
   } catch(Exception ex){
        log.error("Ëxception while sleeping...",e);
   }
   List<PartitionManager> managers = _coordinator.getMyManagedPartitions();
   for (int i = 0; i < managers.size(); i++) {
     ...
     ...
     ...
     ...
}

原因是,kafka消费者在pull methodology的基础上工作,这意味着消费者将从kafka经纪人处获取数据。因此,从消费者的角度来看(Kafka Spout)将持续向kafka经纪人发送一个TCP network request的获取请求。因此,您将面对发送/接收的数据包的大量统计信息。 Though the consumer doesn't consumes any message, pull request and empty response also will get account into network data packet sent/received statistics.如果您的睡眠时间很长,您的网络流量将会减少。经纪人和消费者也有一些network related configurations。进行配置研究可能对您有所帮助。希望它会对你有所帮助。

答案 1 :(得分:0)

您的螺栓是否正在接收消息?你的螺栓是否继承了BaseRichBolt?

在Kafaspout中注释掉行m.fail(id.offset)并检查出来。如果您的螺栓没有确认,那么您的喷口会假定该消息失败并尝试重播相同的消息。

QStandardItemModel *model = new QStandardItemModel(0, 5, this); //reimplemented class
QItemDelegate *mydelegate = new QItemDelegate(this); //reimplemented class

QSortFilterProxyModel * m_proxyModel = new QSortFilterProxyModel();
m_proxyModel -> setSourceModel(model);

ui -> tableView -> setModel( m_proxyModel);
ui -> tableView -> setItemDelegate (mydelegate);
ui -> tableView -> sortByColumn(0, Qt::AscendingOrder);
ui -> tableView -> setSortingEnabled(true);


for(size_t i=0; i<m_BoardingsVector.size(); i++) //a structure from a function that adds rows dynamically
{
        model -> insertRows(model -> rowCount(),1);
        for(int j=0; j<5; ++j)
        ui -> tableView -> openPersistentEditor(model -> index(model -> rowCount() - 1, j));
}

同时尝试暂停nextTuple()几毫秒并检查它。

如果有帮助请告诉我