日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

SOFAMosn 无损重启/升级

發布時間:2025/3/18 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SOFAMosn 无损重启/升级 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

說明,本文檔基于 SOFAMosn 0.4.0 版本編寫

前言

SOFAMosn 是一款采用 GoLang 開發的 Service Mesh 數據平面代理,由螞蟻金服系統部網絡團隊、螞蟻金服中間件團隊、UC 大文娛團隊共同開發,功能和定位類似 Envoy,旨在提供分布式,模塊化,可觀察,智能化的代理能力;她通過模塊化,分層解耦的設計,提供了可編程,事件機制,擴展性,高吞吐量的能力。

——摘自《 SOFAMosn 的誕生和特性》

概述

總體上看,連接遷移的流程如下圖:

  • MOSN 通過 forkexec 生成 New MOSN
  • MOSN 通過 domain socket 把 TCP fd 和請求數據發送給 New MOSN
  • New MOSN 轉發請求到后端(PUB2)
  • 后端 回復響應到 New MOSN
  • New MOSN 通過 MOSN 傳遞來的 TCP fd,回復響應到 client

此后:

  • mosn 退出 readloop,不再接受該 TCP 連接上的數據
  • New mosn 開始 readloop,接受該 TCP 連接上的數據

——摘自《SOFAMosn Introduction》

具體實現

觸發

在 MOSN 啟動的時候,會加載包

github.com/alipay/sofa-mosn/pkg/server

在這個包加載的時候,該里面的 serverkeeper.go 這個文件中的 init() 函數被執行。這個函數會起一個協程在捕獲 HUP 信號。

當 Mosn 接收到來自系統的 HUP 信號時,MOSN 首先會調用 stopStoppable 函數先讓 Admin Server 中的所有 Listener 都關閉 。然后調用 reconfigure 函數來進行配置重新加載。

遷移過程

舊進程的退出

觸發了 reconfigure 函數后,首先 MOSN 會設置兩個環境變量

_MOSN_GRACEFUL_RESTART=true _MOSN_INHERITFD_FD=<number>
  • _MOSN_GRACEFUL_RESTART 對應的包 github.com/alipay/sofa-mosn/pkg/types 中的 GracefulRestart 常量,用于告訴新啟動的 MOSN(下簡稱 New MOSN) 這個是一個優雅重啟。
  • _MOSN_INHERITFD_FD 對應包 github.com/alipay/sofa-mosn/pkg/types 中的 InheritFd 常量,里面存儲的是 ListenerFD 的數量(ListenerFD 就是每個 Listener 調用 listen() 返回的 fd)。
  • 準備好環境變量后,就調用 syscall 包的 ForkExec 按照當前 MOSN 的啟動參數進行啟動,并將環境變量和標準輸入輸出錯誤和 ListenerFD 都和 New MOSN 共享。然后,MOSN 會等 3 秒,讓 New MOSN 啟動起來。認為 New MOSN 啟動完成后,它就會調用 StopAccept() 讓所有的 Listener 停止 Accept 新的請求(已經 Accept 的請求不會結束,socket 的監聽也不會斷),然后調用 WaitConnectionsDone 函數根據 GracefulTimeout(默認是 30秒) 設置的優雅重啟的超時時間讓所有的連接都完畢。接著 MOSN 就進行 Metrics 的遷移,完成后就會退出進程。

    在 WaitConnectionsDone 中,MOSN 設置了一個時間長度為 2 個 GracefulTimeout + 10秒 的時間的定時器。然后首先會 sleep 一個 GracefulTimeout 的時間,等待所有的連接主動關閉。然后關閉所有 server 中 connHandler 的 listeners 成員的 stopChan. 然后再 sleep 一個 GracefulTimeout + 10秒的時間,等待所有連接的遷移。時間過了之后,函數就會返回。此后,上層會調用 TransferMetrics 進行 Metrics 的調用 Exit 進行進程退出。

    新進程的啟動

    繼承 Listener 的獲取

    在 New MOSN 啟動的過程中,首先會調用 getInheritListeners。這個函數會從讀取 Old MOSN 設置的環境變量 _MOSN_GRACEFUL_RESTART,如果為 true, 說明這是一個優雅重啟,就會讀取環境變量 _MOSN_INHERITFD_FD。由于 Listener 是最先使用 fd 的,所以 fd 總是從3 開始,那么所有 Listener fd 就是: 3, 4, ... , 3 + _MOSN_INHERITFD_FD。然后利用這些 fd 將 Old MOSN 的 Listener 恢復出來。從而獲取到繼承過來的 Listener。獲取完之后,會對獲取的 Listener 和配置文件進行比對,判斷其合法性。如果不合法的,或者不能新的配置里面沒有以致繼承過來的 Listener 不需要復用,就會將其關閉。

    完成了所有的初始化之后,就會啟動兩個 Unix Sock 的Server, 分別用與進行連接的遷移和 metrics 的遷移。用于連接遷移的 Unix Sock Server 會在 2 個 GracefulTimeout + 10 秒后自動關閉。

    遷移過程中,New MOSN 對每一個 Unix Sock 請求都會分配一個協程去處理。

    連接的遷移

    當一個請求進來的時候,如果請求使用的協議不是 HTTP1 且不使用系統提供的事件循環的時候,MOSN 會啟動自己的 ConnIo, 調用 startReadLoop 和 startWriteLoop 來開啟針對這個請求的的讀寫循環。

    讀寫數據遷移的協議

    在發送請求的過程中,首先會發送一個字節的數據, 這個字節代表了傳輸的是讀數據遷移還是寫數據遷移。0 代表是使用讀數據遷移協議。1 代表是使用寫數據協議。如果是 0, 還會將該連接的 fd 以 out-of-band 的方式也發送出去。

    讀數據遷移協議

    首先是頭部分:包括 8 個字節,前 4 個字節是 data 部分的長度,后 4 個字節是 TLS 部分的長度。body 部分:接下來 data length 個字節存儲的是 readBuffer 數據。最后 TLS length 個字節存儲的是 TLS 的數據。

    寫數據遷移協議

    頭部分也是 8 個字節, 前 4 個字節存儲了 data 部分長度,后 4 個字節存儲的是 connection ID。body 部分:接下來的 data length 自己存儲的是 writeBuffer 數據。

    讀數據的遷移

    Old MOSN 發送

    在 startReadLoop 中,MOSN 會捕獲之前提到的 stopChan 被關閉的事件。捕獲到這個事件之后,MOSN 會讓這個鏈接等待一個隨機的時間,然后開啟連接遷移的過程。

    首先 MOSN 會往連接中的 transferChan 發一個 transferNotify(值為1) 消息,告訴這個連接對應的寫循環:要開始遷移連接了。然后調用 transferRead 開始遷移讀連接,并返回一個connection ID,最后將這個 ID 再次發送給 transferChan。

    在函數 transferRead 中:

  • 和 New MOSN 先前提到的負責連接遷移的 transferServer 建立 unix socket 連接。
  • 獲取該連接對應的 fd
  • 調用 transferSendType 將傳輸數據使用的協議類型(讀數據遷移協議還是寫數據遷移協議)和連接的 fd 發送給 New MOSN。
  • 調用 transferReadSendData 將 header 部分和 body 部分傳輸給 New MOSN。如果 TLS 握手還沒結束,則 TLS length 為 0。
  • 接收 New MOSN 處理完這些數據之后返回的 connection ID, 并返回
  • New MOSN 的接收

    當 New MOSN 接受到來自 Old MOSN 的數據時:

  • New MOSN 會調用 transferRecvType, 首先接受協議的類型(一個字節), 如果是讀數據遷移的協議,還會去接受 oob(out-of-band)中的 fd,并利用個這個 fd 重建出一個連接,恢復監聽。
  • 調用 transferReadRecvData 獲得本次請求中的 data 部分和 tls 部分的數據。
  • 調用 transferNewConn, 首先根據重建出的連接,找到 NewMOSN 中對應的 Listener。如果這是一個 TLS 連接,還會利用 Old MOSN 傳過來的 TLS 信息將連接重建成一個 TLS 連接。
  • 然后該 Listener 從觸發 Listener 的 OnAccept 事件開始,處理這個連接的請求。當 MOSN 用于封裝連接的 connection 結構體建立完畢后,就標志著這個連接遷移完成,并將這個 connection 結構體存儲在一個叫 transferMap 的數據結構中。
  • 利用重建的 connection 的 id 生成一個本次遷移連接的 ID,回傳給 Old MOSN。
  • 寫數據的遷移

    Old MOSN 的發送

    當寫循環收到讀循環從 transferChan 發過來的 transferNotify 消息時,會再讀一次 transferChan, 獲取到這一次連接傳輸的 ID,如果 ID 合法,則會開始監聽兩個 channel:

  • internalStopChan: 從這個 channel 收到信號(這個 channel 被 close 了),認為這寫數據遷移完成了,會直接退出。
  • writeBufferChan: 這個 channel 傳送過來的是需要寫的數據,也就是需要傳送的數據。收到后就會調用 transferWrite 開始遷移。當 writeLoop 要結束的時候,會 close 掉 internalStopChan 和 writeBufferChan。觸發條件1。
  • 在 transferWrite 中:

  • 和 New MOSN 先前提到的負責連接遷移的 transferServer 建立 unix socket 連接。
  • 調用 transferSendType 將傳輸數據使用的協議類型(讀數據遷移協議還是寫數據遷移協議,此處是寫數據遷移協議)
  • 調用 tranferWriteSendData 將 writeBuffer 里面的內容連同從 New MOSN 返回的連接傳輸 ID 一起發送給 New MOSN
  • New MOSN 的接收

    當 New MOSN 接受到來自 Old MOSN 的數據時:

  • New MOSN 會調用 transferRecvType, 接受協議的類型(一個字節),判斷是寫數據遷移協議,進入接受寫數據遷移的數據流程。
  • 從 unix sock 中讀出要寫的 buffer, 和連接傳輸的 ID
  • 根據 ID 從 transferMap 中 取出對應的 connection 結構體。并讓將傳輸過來的數據扔到 connection 結構體中的 writeBufferChan 中,進入新的 writeLoop。
  • 至此,連接遷移的過成就完成了。

    Metrics 的遷移

    Old MOSN 退出前的最后一件事,就是把 Metrics 數據托付給 New MOSN。

    協議

    Metrics 的傳輸協議很簡單,包括兩部分 header 和 body

  • Header 長度為 4 個字節 存放的是 body length
  • Body 的長度為 body length 個字節。存放著要傳輸的數據,即 Metrics 數據。
  • Old MOSN 的發送
  • 首先他會調 makesTransferData, 將所有的 Metrics 數據都統一收集起來。
  • 和 New MOSN 先前提到的負責 Metrics 遷移的 transferServer 建立 unix socket 連接。
  • 先后把 header 和 body 發送給 New MOSN
  • 如果設置了等待 New MOSN 的響應,會在一個超市時間內等待 New MOSN 1 個字節的返回。
  • New MOSN 的接收

    當 New MOSN 接受到來自 Old MOSN 的數據時,會調 serveConn 函數去處理每一個遷移請求:

  • 讀取數據中的協議頭,并根據協議頭讀取出報文體。
  • 將報文體的數據恢復成成 go-metrics 的數據,供 New MOSN 使用
  • 至此,所有關于平滑重啟的操作就完成了。

    原文地址:https://blog.coordinate35.cn/...

    總結

    以上是生活随笔為你收集整理的SOFAMosn 无损重启/升级的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。