最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang使用ReverseProxy實(shí)現(xiàn)反向代理的方法

 更新時間:2024年09月13日 14:30:39   作者:os-lee  
本文介紹了如何使用Golang的ReverseProxy實(shí)現(xiàn)反向代理,包括源碼結(jié)構(gòu)解析和官方單機(jī)示例NewSingleHostReverseProxy,同時指出,若要實(shí)現(xiàn)負(fù)載均衡,需要自行開發(fā),還提供了一個簡單的HTTP服務(wù)用于測試,感興趣的朋友跟隨小編一起看看吧

1.源碼結(jié)構(gòu)體 

type ReverseProxy struct {
    // Rewrite 必須是一個函數(shù),用于將請求修改為要使用 Transport 發(fā)送的新請求。然后,其響應(yīng)將原封不動地復(fù)制回原始客戶端。返回后,Rewrite 不得訪問提供的 ProxyRequest 或其內(nèi)容。
    // 在調(diào)用 Rewrite 之前,將從出站請求中刪除 Forwarded、X-Forwarded、X-Forwarded-Host 和 X-Forwarded-Proto 標(biāo)頭。另請參閱 ProxyRequest.SetXForwarded 方法。
    // 在調(diào)用 Rewrite 之前,將從出站請求中刪除不可解析的查詢參數(shù)。Rewrite 函數(shù)可以將入站 URL 的 RawQuery 復(fù)制到出站 URL 以保留原始參數(shù)字符串。請注意,如果代理對查詢參數(shù)的解釋與下游服務(wù)器的解釋不匹配,這可能會導(dǎo)致安全問題。
    // 最多可以設(shè)置 Rewrite 或 Director 中的一個。
    Rewrite func(*ProxyRequest)
    // Director 是一種將請求修改為要使用 Transport 發(fā)送的新請求的功能。然后,其響應(yīng)將原封不動地復(fù)制回原始客戶端。Director 在返回后不得訪問提供的請求。
    //默認(rèn)情況下,X-Forwarded-For 標(biāo)頭設(shè)置為客戶端 IP 地址的值。如果 X-Forwarded-For 標(biāo)頭已存在,則客戶端 IP 將附加到現(xiàn)有值。作為特殊情況,如果標(biāo)頭存在于 Request.Header 映射中,但具有 nil 值(例如由 Director func 設(shè)置時),則不會修改 X-Forwarded-For 標(biāo)頭。
    // 為防止 IP 欺騙,請務(wù)必刪除來自客戶端或不受信任的代理的任何預(yù)先存在的 X-Forwarded-For 標(biāo)頭。
    // 在 Director 返回后,將從請求中刪除逐跳標(biāo)頭,這可以刪除 Director 添加的標(biāo)頭。請改用 Rewrite 函數(shù)來確保保留對請求的修改。
    // 如果在 Director 返回后設(shè)置 Request.Form,則會從出站請求中刪除不可解析的查詢參數(shù)。
    // 最多可以設(shè)置 Rewrite 或 Director 中的一個。
    Director func(*http.Request)
    // 用于執(zhí)行代理請求的傳輸。如果為 nil,則使用為 http.DefaultTransport
    Transport http.RoundTripper
    // FlushInterval 指定在復(fù)制響應(yīng)正文時要刷新到客戶端的刷新間隔。如果為零,則不執(zhí)行定期刷新。負(fù)值表示在每次寫入 Client 端后立即刷新。當(dāng) ReverseProxy 將響應(yīng)識別為流式響應(yīng)或其 ContentLength 為 -1 時,將忽略 FlushInterval;對于此類響應(yīng),寫入會立即刷新到客戶端。
    FlushInterval time.Duration
    // ErrorLog 為嘗試代理請求時發(fā)生的錯誤指定可選記錄器。如果為 nil,則通過 log 包的標(biāo)準(zhǔn) logger 完成日志記錄。
    ErrorLog *log.Logger
    // BufferPool 可以選擇指定一個緩沖池,以獲取 io 使用的字節(jié)切片。CopyBuffer 在復(fù)制 HTTP 響應(yīng)正文時。   
    BufferPool BufferPool
    // ModifyResponse 是一個可選函數(shù),用于修改來自后端的 Response。如果后端返回帶有任何 HTTP 狀態(tài)代碼的響應(yīng),則調(diào)用它。如果無法訪問后端,則調(diào)用可選的 ErrorHandler,而不調(diào)用 ModifyResponse。如果 ModifyResponse 返回錯誤,則調(diào)用 ErrorHandler 及其錯誤值。如果 ErrorHandler 為 nil,則使用其默認(rèn)實(shí)現(xiàn)。
    ModifyResponse func(*http.Response) error
    // ErrorHandler 是一個可選函數(shù),用于處理到達(dá)后端的錯誤或來自 ModifyResponse 的錯誤。如果為 nil,則默認(rèn)記錄提供的錯誤并返回 502 Status Bad Gateway 響應(yīng)。    
    ErrorHandler func(http.ResponseWriter, *http.Request, error)
}

2.官方單機(jī)示例

NewSingleHostReverseProxy是官方給的示例,代理單機(jī)服務(wù),如果想實(shí)現(xiàn)負(fù)載均衡,需自己實(shí)現(xiàn)。

源碼:

3.使用示例

package main
import (
	"log"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"sync"
	"time"
)
// 從Go 1.18版本開始,httputil.ReverseProxy 的 BufferPool 字段期望的是一個實(shí)現(xiàn)了 BufferPool 接口的對象,該接口要求有一個返回 []byte 的 Get 方法和一個接受 []byte 的 Put 方法。
// 定義一個實(shí)現(xiàn)了 BufferPool 接口的結(jié)構(gòu)體
// 定義一個實(shí)現(xiàn)了 BufferPool 接口的結(jié)構(gòu)體
type byteBufferPool struct {
	sync.Pool
}
// 實(shí)現(xiàn) BufferPool 接口的 Get 方法
func (b *byteBufferPool) Get() []byte {
	v := b.Pool.Get()
	if v == nil {
		return make([]byte, 1024*1024) // 分配 1MB 的緩沖區(qū)
	}
	return v.([]byte)
}
// 實(shí)現(xiàn) BufferPool 接口的 Put 方法
func (b *byteBufferPool) Put(bts []byte) {
	b.Pool.Put(bts)
}
// 定義一個實(shí)現(xiàn)了 ErrorHandler 接口的函數(shù)
func customErrorHandler(w http.ResponseWriter, r *http.Request, err error) {
	// 記錄錯誤
	log.Printf("Error occurred: %v", err)
	// 返回自定義的狀態(tài)碼和錯誤消息
	w.WriteHeader(http.StatusInternalServerError)
	w.Write([]byte("An internal error occurred."))
}
func main() {
	// 目標(biāo)服務(wù)器的 URL
	targetURL := "http://localhost:8081"
	// 解析目標(biāo) URL
	target, err := url.Parse(targetURL)
	if err != nil {
		log.Fatalf("Failed to parse target URL: %v", err)
	}
	// 創(chuàng)建反向代理
	proxy := httputil.NewSingleHostReverseProxy(target)
	// 設(shè)置 FlushInterval
	// FlushInterval 是一個 time.Duration 類型的字段,它指定了代理服務(wù)器將緩沖的數(shù)據(jù)寫入客戶端的間隔時間。這對于實(shí)現(xiàn)實(shí)時應(yīng)用(如實(shí)時聊天、日志流等)非常重要,因?yàn)樗梢詼p少延遲,讓客戶端更快地接收到數(shù)據(jù)。
	proxy.FlushInterval = 100 * time.Millisecond
	// 設(shè)置反向代理的 Transport
	proxy.Transport = &http.Transport{
		DialContext: (&net.Dialer{
			Timeout:   30 * time.Second, // 建立連接的最大等待時間
			KeepAlive: 30 * time.Second, // 保持連接活躍的時間間隔
			DualStack: true,             // 嘗試同時使用 IPv4 和 IPv6 地址
		}).DialContext,
		MaxIdleConns:          100,              // 最大空閑連接數(shù)
		IdleConnTimeout:       90 * time.Second, // 空閑連接超時時間
		TLSHandshakeTimeout:   10 * time.Second, // TLS握手超時時間
		ExpectContinueTimeout: 1 * time.Second,  // Expect: 100-continue 超時時間
	}
	// 創(chuàng)建自定義的日志器
	proxy.ErrorLog = log.New(os.Stderr, "ERROR: ", log.LstdFlags)
	// 設(shè)置反向代理的 BufferPool 緩沖池
	proxy.BufferPool = &byteBufferPool{
		Pool: sync.Pool{
			New: func() interface{} {
				return make([]byte, 1024*1024) // 分配 1MB 的緩沖區(qū)
			},
		},
	}
	// 設(shè)置反向代理的 ModifyResponse
	proxy.ModifyResponse = func(res *http.Response) error {
		// 修改響應(yīng)頭
		res.Header.Set("X-Modified-By", "ReverseProxy")
		// 修改狀態(tài)碼(示例)
		res.StatusCode = 200
		// 返回 nil 表示繼續(xù)處理
		return nil
	}
	// 設(shè)置反向代理的 ErrorHandler
	proxy.ErrorHandler = customErrorHandler
	// 創(chuàng)建 HTTP 服務(wù)器
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		// 調(diào)用反向代理
		proxy.ServeHTTP(w, r)
	})
	// 啟動 HTTP 服務(wù)器
	log.Println("Starting server on :8080")
	log.Fatal(http.ListenAndServe(":8080", nil))
}

4.簡單的http服務(wù)(用于測試)

package main
import (
	"fmt"
	"log"
	"net/http"
)
func helloWorldHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, World!")
}
func main() {
	http.HandleFunc("/", helloWorldHandler)
	log.Println("Starting server on :8081")
	log.Fatal(http.ListenAndServe(":8081", nil))
}

到此這篇關(guān)于Golang使用ReverseProxy實(shí)現(xiàn)反向代理的文章就介紹到這了,更多相關(guān)Golang ReverseProxy反向代理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go?語言使用goroutine運(yùn)行閉包踩坑分析

    Go?語言使用goroutine運(yùn)行閉包踩坑分析

    這篇文章主要介紹了Go?語言使用goroutine運(yùn)行閉包踩坑解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • Go設(shè)計模式之模板方法模式講解和代碼示例

    Go設(shè)計模式之模板方法模式講解和代碼示例

    模版方法是一種行為設(shè)計模式, 它在基類中定義了一個算法的框架, 允許子類在不修改結(jié)構(gòu)的情況下重寫算法的特定步驟,本文將通過代碼示例給大家詳細(xì)的介紹一下Go模板方法模式,需要的朋友可以參考下
    2023-08-08
  • Go語言sync.Pool對象池使用場景基本示例

    Go語言sync.Pool對象池使用場景基本示例

    這篇文章主要為大家介紹了Go語言sync.Pool對象池使用場景的基本示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • 基于Golang實(shí)現(xiàn)內(nèi)存數(shù)據(jù)庫的示例詳解

    基于Golang實(shí)現(xiàn)內(nèi)存數(shù)據(jù)庫的示例詳解

    這篇文章主要為大家詳細(xì)介紹了如何基于Golang實(shí)現(xiàn)內(nèi)存數(shù)據(jù)庫,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,需要的小伙伴可以參考一下
    2023-03-03
  • 服務(wù)器端Go程序?qū)﹂L短鏈接的處理及運(yùn)行參數(shù)的保存

    服務(wù)器端Go程序?qū)﹂L短鏈接的處理及運(yùn)行參數(shù)的保存

    這篇文章主要介紹了服務(wù)器端Go程序?qū)﹂L短鏈接的處理及運(yùn)行參數(shù)的保存,這里針對使用Go語言編寫的Socket服務(wù)器進(jìn)行實(shí)例說明,需要的朋友可以參考下
    2016-03-03
  • Go基于雪花算法生成隨機(jī)id

    Go基于雪花算法生成隨機(jī)id

    雪花算法是twitter開源的由64位整數(shù)組成的分布式ID,本文主要介紹了Go基于雪花算法生成隨機(jī)id,具有一定的參考價值,感興趣的可以了解一下
    2024-05-05
  • golang連接MongoDB數(shù)據(jù)庫及數(shù)據(jù)庫操作指南

    golang連接MongoDB數(shù)據(jù)庫及數(shù)據(jù)庫操作指南

    MongoDB是Nosql中常用的一種數(shù)據(jù)庫,下面這篇文章主要給大家介紹了關(guān)于golang連接MongoDB數(shù)據(jù)庫及數(shù)據(jù)庫操作的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09
  • go語言解決并發(fā)問題小結(jié)

    go語言解決并發(fā)問題小結(jié)

    并發(fā)是GO最基本的功能了,但是在傳統(tǒng)的PHP中是比較困難的,如果不借助其它一些擴(kuò)展的話,是做不到并發(fā)的,這篇文章主要介紹了go語言如何解決并發(fā)問題,需要的朋友可以參考下
    2024-05-05
  • Go語言基礎(chǔ)if條件語句用法及示例詳解

    Go語言基礎(chǔ)if條件語句用法及示例詳解

    這篇文章主要為大家介紹了Go語言基礎(chǔ)if條件語句的用法及示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2021-11-11
  • Go?mod?replace使用方法及常見問題分析

    Go?mod?replace使用方法及常見問題分析

    這篇文章主要為大家介紹了Go?mod?replace使用方法及常見問題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08

最新評論

鱼台县| 民和| 襄城县| 娱乐| 连江县| 梁山县| 鸡西市| 弥渡县| 江达县| 利川市| 汪清县| 徐闻县| 清河县| 长春市| 柘城县| 晋州市| 慈溪市| 竹山县| 三都| 大城县| 含山县| 樟树市| 海口市| 黄骅市| 东城区| 海城市| 石景山区| 电白县| 邻水| 梁河县| 平南县| 兴城市| 称多县| 龙游县| 宜兰县| 自贡市| 苍山县| 治多县| 金山区| 宜宾县| 米泉市|