DelayedOperationPurgatory--謎之煉獄

  • 在kafka中有很多操作需要延遲等待, 比如客戶端發送數據到達leader后, 根據設置ack方式不同,需要等待其replicas返回ack, 那這個ack就需要延遲等待;對于一個拉取操作, 需要延遲等待期望拉取的字節數準備好;
  • 有延遲操作, 那必然會存在操作的超時處理. 還記得我們上一篇Kafka中的時間輪中對Timer的分析吧, 這里的延遲操作需要使用它來實現;

DelayedOperation
  • 所在文件: core/src/main/scala/kafka/server/DelayedOperation.scala
  • 這是個抽象類, 所有具體的延遲任務都需要繼承這個類;
  • 同時每個延遲任務必然存在操作的超時, 那么其超時操作是通過將對象放到Kafka中的時間輪中的Timer中處理, 因此這個類又繼承自TimerTask;
  • private val completed = new AtomicBoolean(false): 原子變量, 標識當前operation是否已完成;
  • def forceComplete(): Boolean: 強制完成操作;
if (completed.compareAndSet(false, true)) {
      // cancel the timeout timer
      cancel()
      onComplete()
      true
    } else {
      false
    }

分兩種情況:

  1. 當前操作已經完成,則不再需要強制完成,返回false;
  2. 當前操作未完成, 則首先在Timer中取消這個定時任務, 然后回調onComplete
  • override def run(): Unit: 實現的是TimerTask的方法, 當超時時會執行此操作:
if (forceComplete())
      onExpiration()

里面的操作比較簡單, 調用forceComplete, 如果成功,表明是真的超時了,回調onExpiration;

  • 需要由子類實現的方法:
  1. def onExpiration(): Unit: 超時后的回調處理;
  2. def onComplete(): Unit: 操作完成后的回調處理;
  3. def tryComplete(): Boolean: 在放入到Timer前, 先嘗試著執行一下這個操作, 看是否可以完成, 如果可以就不用放到Timer里了, 這是為了確保任務都盡快完成作的一個優化;
Watchers
  • 所在文件: core/src/main/scala/kafka/server/DelayedOperation.scala
  • 對于一個延遲任務, 一般會有兩個操作加持在身:
  1. 上面說的作為超時任務放在Timer中;
  2. 與某些事件關聯在一起, 可以關聯多個事件, 當這些事件中的某一個發生時, 這個任務即可認為是完成;這個就是 Watchers類要完成的工作;
  • class Watchers(val key: Any): 構造時需要一個參數key, 你可以理解成是一個事件;
  • private[this] val operations = new LinkedList[T](): 用于存放和這個key關聯的所有操作,一個key可以關聯多個操作, 同時一個操作也可以被多個key關聯(即位于多個Watchers對象中)
  • def purgeCompleted(): Int: 刪除鏈表中所有已經完成的操作
      var purged = 0
      operations synchronized {
        val iter = operations.iterator()
        while (iter.hasNext) {
          val curr = iter.next()
          if (curr.isCompleted) {
            iter.remove()
            purged += 1
          }
        }
      }
      if (operations.size == 0)
        removeKeyIfEmpty(key, this)

      purged
    }
  • def tryCompleteWatched(): Int:
     var completed = 0
      operations synchronized {
        val iter = operations.iterator()
        while (iter.hasNext) {
          val curr = iter.next()
          if (curr.isCompleted) {
            // another thread has completed this operation, just remove it
            iter.remove()
          } else if (curr synchronized curr.tryComplete()) {
            completed += 1
            iter.remove()
          }
        }
      }

      if (operations.size == 0)
        removeKeyIfEmpty(key, this)

      completed

掃描整個鏈表:

  1. 如果任務已完成,則移除;
  2. 如果任務未完成, 調用tryComplete嘗試立即完成, 如果可以完成, 則移除;
  • 添加任務:
def watch(t: T) {
      operations synchronized operations.add(t)
    }
DelayedOperationPurgatory
  • 所在文件: core/src/main/scala/kafka/server/DelayedOperation.scala
  • 終于要揭開我們的謎之煉獄啦, 源碼里的注釋如下:

A helper purgatory class for bookkeeping delayed operations with a timeout, and expiring timed out operations

實際上就是用來通過TimerWatchers來管理一批延遲任務;

  • private[this] val timeoutTimer = new Timer(executor): 用來處理加入的作務的超時行為;
  • private val expirationReaper = new ExpiredOperationReaper():
private class ExpiredOperationReaper extends ShutdownableThread(
    "ExpirationReaper-%d".format(brokerId),
    false) {

    override def doWork() {
      timeoutTimer.advanceClock(200L)

      if (estimatedTotalOperations.get - delayed > purgeInterval) {
        estimatedTotalOperations.getAndSet(delayed)
        debug("Begin purging watch lists")
        val purged = allWatchers.map(_.purgeCompleted()).sum
        debug("Purged %d elements from watch lists.".format(purged))
      }
    }
  }
  1. timeoutTimer.advanceClock(200L): 驅動Timer向前走, pop出超時的延遲任務;
  2. val purged = allWatchers.map(_.purgeCompleted()).sum: 利用閾值(purgeInterval)來周期性地從Watchers中清理掉已經完成的任務;
  • def tryCompleteElseWatch(operation: T, watchKeys: Seq[Any]): Boolean: 將operation和一系列的事件(key)關聯起來, 然后調用tryComplete嘗試立即完成該操作,如果不能完成,加入到Timer中;

  • def checkAndComplete(key: Any): Int: 按key找到相應的Watchers對象, 然后調用其tryCompleteWatched(), 說明上面用;

簡圖:
DelayedOperation.png
基本上就是這些了

Kafka源碼分析-匯總

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容