frp 0.22.0 及 0.23.0 更新解讀

2021-02-14 路由器的那些事兒
為了獲得更好的閱讀體驗,查看完整的代碼,獲得最新的更新之後的文章內容,建議點擊 "原文連結" 查看原文。

frp 是一個可用於內網穿透的高性能的反向代理應用,支持 tcp, udp 協議,為 http 和 https 應用協議提供了額外的能力,且嘗試性支持了點對點穿透。(來自frp官方文檔: https://github.com/fatedier/frp/blob/master/README_zh.md)如果你不知道什麼是frp,你可以查看一下官方文檔了解更多信息。

frp 0.22.0 及 0.23.0 更新解讀

本文主要是配合changelog從代碼層面來解讀這次的更新。

frp作者於今天下午發布了 0.23.0 版本,就在這時我還在寫0.22.0 的更新解讀,還沒寫完,於是現在文章 的標題變成了0.22.0 和 0.23.0 的更新解讀了。

另,0.23.0 有一個不算bug的「bug」, 嚴格來說算一個typo, 由於我第一時間編譯並測試了,因此fix了這個在dashboard會看不到任何proxy的問題。(git commit: https://github.com/fatedier/frp/commit/0bd8f9cd9bc8a63d849bf23e014acded8808a76b)

我提交了一個PR, 目前已經被合併到主線master分支了。

另外,無燈最新的frps和frpc 已經應用了此patch.

下載地址:

http://files.80x86.io/router/rom/opt/frp/

0.23.0 更新

改變:frps 中的 auth_timeout 參數被移除

增加功能:配置文件模版渲染 (配置文件支持使用系統環境變量進行模版渲染,模版格式採用 Go 的標準格式)

https://github.com/fatedier/frp/blob/655c52f9cea69a60911844e5c291c2f0eb9b2fcd/README_zh.md#%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E6%A8%A1%E7%89%88%E6%B8%B2%E6%9F%93

例如:

 

示例配置如下:

# frpc.ini

[common]

server_addr = {{ .Envs.FRP_SERVER_ADDR }}

server_port = 7000

[ssh]

type = tcp

local_ip = 127.0.0.1

local_port = 22

remote_port = {{ .Envs.FRP_SSH_REMOTE_PORT }}

啟動 frpc 程序:

 

export FRP_SERVER_ADDR="x.x.x.x"

export FRP_SSH_REMOTE_PORT="6000"

./frpc -c ./frpc.ini

個人看法,這種配置方式,可能更加方便golang程式設計師開發和調試吧。對於普通用戶來說,好像沒有太多用處。

frp 0.22.0 更新

https://github.com/fatedier/frp/releases/tag/v0.22.0

bug 修復咱就不說了,沒有太多影響,不是緊要的bug.

關注一下新增加的功能

Support health check for each proxy in frpc.

配置文件方面,增加了結構 HealthCheckConf (https://github.com/fatedier/frp/blob/698219b6218897241aef7e148e2e611f9b8c6ccf/models/config/proxy.go#L381):

 

type HealthCheckConf struct {

    HealthCheckType      string `json:"health_check_type"` 

    HealthCheckTimeout   int    `json:"health_check_timeout"`

    HealthCheckMaxFailed int    `json:"health_check_max_failed"`

    HealthCheckIntervalS int    `json:"health_check_interval_s"`

    HealthCheckUrl       string `json:"health_check_url"`

    

    HealthCheckAddr string `json:"-"`

}

根據  https://github.com/fatedier/frp/commit/c33b5152e722a50d65cd6925ba498f3016c7c19c#diff-84745d65d0dd850a2c083879213a24fb

對於tcp類型的檢測:

增加以下配置即可

 

# enable health check for the backend service, it support 'tcp' and 'http' now

# frpc will connect local service's port to detect it's healthy status

health_check_type = tcp

health_check_max_failed = 3

health_check_interval_s = 10

http類型的檢測,增加以下配置即可:

 

health_check_type = http

# frpc will send a GET http request '/status' to local http service

# http service is alive when it return 2xx http response code

health_check_url = /status

health_check_max_failed = 3

health_check_interval_s = 10

當frpc檢測到對應的health check項失敗次數達到 health_check_max_failed 次數時,

就會將此proxy從服務端(frps)移除. 在代碼中表現為:發送一個 CloseProxyMsg 到服務端.

相關代碼:

 client/health/health.go

 

func (monitor *HealthCheckMonitor) checkWorker() {

    

            if monitor.l != nil {

                monitor.l.Warn("do one health check failed: %v", err)

            }

            monitor.failedTimes++

            if monitor.statusOK && int(monitor.failedTimes) >= monitor.maxFailedTimes && monitor.statusFailedFn != nil {

                if monitor.l != nil {

                    monitor.l.Warn("health check status change to failed")

                }

                monitor.statusOK = false

                monitor.statusFailedFn()

            }

}

當檢測失敗並且實際失敗次數 monitor.failedTimes 大於等於 最大失敗次數 monitor.maxFailedTimes 時,

並且 statusFailedFn 不是 nil, 則執行 monitor.statusFailedFn()

statusFailedFn 是在func NewHealthCheckMonitor(checkType string, intervalS int, timeoutS int, maxFailedTimes int, addr string, url string,
    statusNormalFn func(), statusFailedFn func()) *HealthCheckMonitor 函數中設定的。

  client/proxy/proxy_wrapper.go 裡的NewProxyWrapper() 會調用  health.NewHealthCheckMonitor() ,設置 statusFailedFn 為 pw.statusFailedCallback,我們看下它的代碼:

 

func (pw *ProxyWrapper) statusFailedCallback() {

    atomic.StoreUint32(&pw.health, 1)

    errors.PanicToError(func() {

        select {

        case pw.healthNotifyCh <- struct{}{}:

        default:

        }

    })

    pw.Info("health check failed")

}

然後再看proxy是如何關閉的:

 client/proxy/proxy_wrapper.go 裡的 func (pw *ProxyWrapper) checkWorker()

 

func (pw *ProxyWrapper) checkWorker() {

    if pw.monitor != nil {

        

        time.Sleep(500 * time.Millisecond)

    }

    for {

        

        now := time.Now()

        if atomic.LoadUint32(&pw.health) == 0 {

           //...

        } else {

            pw.mu.Lock()

            if pw.Status == ProxyStatusRunning || pw.Status == ProxyStatusWaitStart {

                pw.handler(event.EvCloseProxy, &event.CloseProxyPayload{

                    CloseProxyMsg: &msg.CloseProxy{

                        ProxyName: pw.Name,

                    },

                })

                pw.Trace("change status from [%s] to [%s]", pw.Status, ProxyStatusCheckFailed)

                pw.Status = ProxyStatusCheckFailed

            }

            pw.mu.Unlock()

        }

        select {

        case <-pw.closeCh:

            return

        case <-time.After(statusCheckInterval):

        case <-pw.healthNotifyCh:

        }

    }

}

這裡,關閉proxy的主要代碼是:

 

                pw.handler(event.EvCloseProxy, &event.CloseProxyPayload{

                    CloseProxyMsg: &msg.CloseProxy{

                        ProxyName: pw.Name,

                    },

                })

                pw.Trace("change status from [%s] to [%s]", pw.Status, ProxyStatusCheckFailed)

                pw.Status = ProxyStatusCheckFailed

pw.handler又是個啥呢? 這個欄位在NewProxyWrapper() 中設置,具體調用在proxy_manager.go中有:

 

pxy := NewProxyWrapper(cfg, pm.HandleEvent, pm.logPrefix)

pm.proxies[name] = pxy

然後,我們再看 pm.HandleEvent :

 

func (pm *ProxyManager) HandleEvent(evType event.EventType, payload interface{}) error {

    var m msg.Message

    switch e := payload.(type) {

    case *event.StartProxyPayload:

        m = e.NewProxyMsg

    case *event.CloseProxyPayload:

        m = e.CloseProxyMsg

    default:

        return event.ErrPayloadType

    }

    err := errors.PanicToError(func() {

        pm.sendCh <- m

    })

    return err

}

 對於關閉的情況,傳入的第2個參數是: event.CloseProxyPayload , 因此會發送 CloseProxyMsg 到  pm.sendCh

pm.sendCh 又是個啥呢?

client/control.go 

 

ctl.pm = proxy.NewProxyManager(ctl.sendCh, runId)

從代碼可看出,實際調用的時候是傳入 ctl.sendCh

消息是在client/control.go的 func (ctl *Control) writer() 方法中發送給frps的:

msg.WriteMsg(encWriter, m)

 

m, ok := <-ctl.sendCh

msg.WriteMsg(encWriter, m)

當然,msg.WriteMsg 又進行了一層包裝. 這裡就不進一步分析了.

add module comments for vgo

這個修改主要是為了兼容新版本的vgo (GO111MODULE).

https://github.com/fatedier/frp/commit/42ee536dae2ace3d423de6c5262819b71e82312c

主要是對main包加了注釋,類似這樣:

 

package main 

package main 

為了獲得更好的閱讀體驗,查看完整的代碼,獲得最新的更新之後的文章內容,建議點擊 "原文連結" 查看原文。

--EOF

相關焦點

  • frp 0.13.0 發布,內網穿透工具 - OSCHINA - 中文開源技術交流社區
    內網穿透工具 frp 0.13.0 發布了。
  • 奧數,計算多項式,(1+0.23+0.34)*(0.23+0.34+0.65)-……
    計算多項式,(1+0.23+0.34)*(0.23+0.34+0.65)-(1+0.23+0.34+0.65)*(0.23+0.34),題目非常的長,但是該如何計算呢?最直接的一個方法就是直接計算,但是這個方法太過於繁瑣。至少要列出十幾個算式,而且想想我們學過的運算定律和性質。分配律,結合律。好像都用不上。那麼該如何計算呢?
  • 《cf》23-0是什麼意思 23-0意思介紹
    導 讀cf23-0的意思是安全系統檢測到你的遊戲數據存在異常時會提示"23-0"。
  • 《逃離塔科夫》0.12.7更新了哪些 0.12.7更新內容一覽
    導 讀 逃離塔科夫0.12.7更新了什麼,遊戲也是在7月16日進行了更新,那麼0.12.7版本都更新了什麼呢
  • 列豎式計算:1.8×23;0.37×0.4;1.06×25;0.082×0.14等
    1.8×23 0.37×0.4 1.06×25 0.082×0.147×0.86 0.6×0.39 27×0.43 0.055×0.06普通學生思路:小數乘法計算方法:1.先按照整數乘法算出積
  • 帕斯卡契約1.0.9更新內容 帕斯卡契約1.0.9更新了什麼
    帕斯卡契約1.0.9更新了什麼?近日帕斯卡契約發布了第一個更新補丁,這次的更新補丁內容可能還是有些玩家不太清楚具體的更新內容吧。昨晚一款單機遊戲,更新的內容是什麼呢?本次的更新主要是應對遊戲的一些BUG,讓我們一起來看一下詳細更新內容。
  • 一加5/5T發布氫OS 9.0.0版本更新 基於安卓9.0集成谷歌鏡頭模式
    【TechWeb】一加官方在聖誕節當天宣布為一加手機5和一加手機5T發布氫OS 9.0.0版本更新,此次更新將會帶來基於安卓9.0的全新系統版本,這兩款手機的用戶現在就可以通過OTA來進行升級了。此次9.0.0版本也是在經歷了22個測試版之後發布的首個正式版。
  • 0.從0開始的手寫java虛擬機-解讀class文件
    00 02 00 03 07 00 04 0C 00 05 00 06 01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74 01 00 06 3C 69 6E 69 74 3E 01 00 03 28 29 56 09 00 08 00 09 07 00 0A 0C 00 0B 00 0C 01 00 10 6A 61 76 61 2F
  • xmnlp v0.3.0 更新:使用及原理介紹
    封面與正文無關自從 19 年畢業正式工作後,已經好久沒更新過這個公眾號,在帳號被凍結之際,更新一篇。新的一年,計劃多更新一下文章,就當做總結反思吧。
  • PyTorch 重大更新,0.4.0 版本支持 Windows 系統
    雷鋒網(公眾號:雷鋒網) AI 研習社最新消息,PyTorch 官方發布0.4.0 版本,該版本的 PyTorch 有多項重大更新,其中最重要的改進是支持 Window 系統。以下為 PyTorch 0.4.0 版本主要更新內容:主要核心改變Tensor/Variable 合併
  • 為什麼 0.1 + 0.2 = 0.300000004 ?
    0.375 在二進位表示看來確實是『整數』。然而如下圖所示,想要使用二進位表示十進位中的 0.1 和 0.2 是比較複雜的:float-and-double圖 4 - 單精度與雙精度浮點數單精度浮點數 float 總共包含 32 位,其中 1 位表示符號、8 位表示指數,最後 23
  • 任天堂Swtich 7.0.0版本系統更新 中文系統上線
    【TechWeb】今天(1月29日),任天堂正式向全球Nintendo Swtich玩家推送了7.0.0系統版本更新,Swtich的中文系統終於到來,而「簡體中文/English」和「繁體中文/English」終於成為了過去式。
  • 日誌收集工具 logpipe 更新至 0.9.0 版本
    日誌收集工具 logpipe 0.9.0 已發布。
  • 騰訊TIM全新3.0.0更新!
    如標題,TIM終於更新了!!!不過,回想TIM上一次重大更新距今大概有一年多時間了,我時不時會在QQ群啊,微信群啊,百度上啊看到一群網易會在聊TIM什麼時候更新?騰訊是不是放棄TIM了?TIM團隊是不是解散了?什麼亂七八糟的猜想,本次重大更新可見,這些猜想都是不存在的啦!話說這騰訊也是,不更新吧,好幾個月不更新,而且一更新就是重大更新!這真的是「短暫的離別,是為了更好的遇見!」
  • 0!0!0!江門連續7天無新增!新冠肺炎英文名稱修訂!
    0!0!0!江門連續7天無新增!新冠肺炎英文名稱修訂!累計報告確診病例中,深圳市417例、廣州市345例、珠海市98例、東莞市94例、佛山市84例、中山市66例、惠州市62例、汕頭市25例、江門市23例、湛江市22例、肇慶市19例、梅州市16例、茂名市14例、陽江市13例、清遠市12例、韶關市10例、揭陽市8例、汕尾市5例、潮州市5例、河源市4例。男性661例,女性681例,年齡介於2月齡-90歲之間。
  • jSqlBox 2.0.0 版本更新,全棧資料庫持久層工具
    jSqlBox2.0.0已發布,V2.0.0版本更新添加了分庫分表等多處更新,並提供了Java8版本。
  • PC遊戲模擬器ScummVM 0.10.0更新支持PSP2000
    更新說明:  新版本增加了新引擎的支持,可以模擬運行的遊戲數量更多。下載&運行:  如果您是1.5版PSP  將文件夾解壓,拷貝「scummvm-0.10.0-psp\1.50-eboot」目錄下的兩個程序文件夾到PSP記憶棒中的「PSP\GAME」目錄下即可。
  • 半場-西班牙人0-0馬洛卡,德託馬斯造險
    北京時間2月9日晚19:00,西班牙人在西甲第23輪主場迎戰馬洛卡。 上半場,西班牙人有數次破門機會,但沒有把握住,主裁判一次錯誤判罰給了馬洛卡點球,但隨後VAR判定皮球出界在先,點球被撤回,上半場兩隊暫時0-0平手。
  • RichFaces 4.0.0 更新發行計劃
    RichFaces 團隊日前對 4.0 版本剩餘的功能進行評審,為了保證項目的質量決定修改發行時間安排。
  • 浮點數0.1+0.2為何不等於0.3
    你會發現,我們這個公式無法表示0,的確,這是一個巧妙的設計,我們用0(8個bit都為0)和255(8個bit都為1)來表示一些特殊的數值,可以認為他們2個是特殊的flag位,比如當e和f都為0的時候,我們就認為這個浮點數是0,看下表: