從字面意思上看,代理就是代替處理的意思,一個對象有能力代替另一個對象處理某一件事。
代理,這個詞在我們的日常生活中也不陌生,比如在購物、旅游等場景中,我們經常會委托別人代替我們完成某些任務。在技術領域,這個概念也被廣泛應用,尤其是在計算機網絡通信和程序設計中,代理扮演著相當重要的角色,涉及控制訪問、安全保護、能力擴展等復雜而強大的方面。
在計算機網絡中,說到代理,經常會談到正向代理和反向代理的概念。
在詳細展開前,我們先使用一個比喻來形象的理解下這兩個概念:小明去飯館吃飯,正向代理就像是小明的朋友幫他去點餐,服務員并不知道最終吃飯的人是小明;而反向代理則像是飯館的服務員,他們決定把小明的訂單送到哪個廚師手里去做。通過這個比喻,我們可以初步感受到正向代理和反向代理在角色和功能上的不同。
搞清楚網絡通信中的代理和反向代理,大家只要弄明白兩件事:你在公司的電腦是怎么訪問到外網的,你部署的網站或者API又是怎么被外網訪問到的。
首先看公司電腦上網:公司里的電腦一般不會直接連接到互聯網,它們通常在一個內網環境中,這既有成本的考慮,也有安全控制的需要。辦公電腦一般會先連接到交換機,交換機再連接到路由器,路由器再連接到互聯網。
在這些連接中,交換機只是一個小透明,辦公電腦可以看到路由器,路由器也可以看到辦公電腦,所以交換機不是我們這里所說的代理。
這里真正的代理是路由器,辦公電腦訪問網絡時,請求先到達路由器,路由器做個請求來源的登記,記下這個請求是從哪臺電腦發出的,然后再發到互聯網上。請求出了路由器,互聯網上能夠看到的就是這個路由器,而看不到你的辦公電腦。數據從遠程服務器返回時,也是先到達這個路由器,路由器再根據之前做的請求來源登記,將數據轉發到對應的辦公電腦上。
這種場景下,路由器就是一個正向代理,代理內網電腦訪問互聯網。
圖片
除了使用路由器這種比較常見的代理方式,其實還有很多方式,比如在瀏覽器中配置HTTP代理,只允許通過瀏覽器訪問外網。
再看網站或者API是怎么被外網訪問到的:通常情況下,大家的服務器也是放在內網中的,直接暴露在互聯網上會有安全風險,也不利于管理。所以,我們會在服務器和互聯網之間設置一個代理服務器,通常是Nginx或者LVS這種負載均衡器。當外網的用戶想要訪問你的網站或API時,他們的請求首先會發送到這個代理服務器上。
這個代理服務器就是一個反向代理。
圖片
反向代理服務器接到請求后,它知道內網中哪臺服務器能提供這個服務,于是它就把請求轉發給對應的服務器。服務器處理完這個請求后,再把結果發送回反向代理服務器,最后由反向代理服務器返回給外網的用戶。
以上就是計算機網絡中正向代理和反向代理的基本原理和應用場景,我們再做一個對比,加深印象。
正向代理和反向代理的區別主要體現在它們服務的對象和用途上:
對比項 | 正向代理(Forward Proxy) | 反向代理(Reverse Proxy) |
服務對象 | 客戶端 | 服務器 |
主要用途 | - 幫助客戶端訪問無法直接訪問的資源 - 進行訪問控制和緩存以提高速度和安全性 | - 隱藏服務器真實IP地址 - 提供負載均衡功能 - 提高服務器訪問速度和安全性 |
工作方式 | - 客戶端配置代理服務器,請求先發送至代理服務器 - 代理服務器代為訪問目標服務器并返回資源給客戶端 | - 客戶端請求發送至反向代理服務器 - 反向代理服務器根據配置轉發請求到內部網絡的特定服務器 - 從服務器獲取響應后返回給客戶端 |
舉例說明 | - 使用瀏覽器設置代理服務器,所有上網請求經由代理服務器訪問互聯網資源 | - 根據負載均衡策略將用戶請求分發到不同服務器處理 |
簡單來說,正向代理是客戶端的代理,幫助客戶端訪問到無法直接獲取的資源;反向代理是服務器的代理,幫助服務器平滑處理來自各方的請求。
在程序設計中,也有一個代理模式,雖然和網絡中的正向代理或反向代理的概念不完全一樣,但本質上它們都是代理的概念,都是作為中介提供隔離、隱藏、控制訪問和功能增強等作用。
Just show me the code! 現在我們用Go來編寫一個代理的實例程序,假設我們有一個資源類,我們希望在訪問這個資源時,記錄訪問次數,并在資源不再被引用時自動釋放資源。
首先,定義一個資源接口Resource和實現這個接口的資源類MyResource:
package mainimport ( "fmt")// Resource 接口定義了資源需要實現的方法type Resource interface { Use() Release()}// MyResource 是實現了Resource接口的資源類type MyResource struct{}func (r *MyResource) Use() { fmt.Println("Using MyResource")}func (r *MyResource) Release() { fmt.Println("Releasing MyResource")}
然后,定義一個代理的類 ResourceProxy,它包含了對資源的引用和引用計數,同時它也實現了Resource接口。
// ResourceProxy 是代理的結構體,包含資源和引用計數type ResourceProxy struct { resource Resource refCount int}// NewResourceProxy 是ResourceProxy的構造函數func NewResourceProxy(resource Resource) *ResourceProxy { return &ResourceProxy{resource: resource, refCount: 1} // 初始引用計數為1}// Use 方法增加引用計數并使用資源func (sr *ResourceProxy) Use() { sr.refCount++ fmt.Printf("Resource is used %d times/n", sr.refCount) sr.resource.Use()}// Release 方法減少引用計數,當計數為0時釋放資源func (sr *ResourceProxy) Release() { sr.refCount-- if sr.refCount == 0 { sr.resource.Release() } else { fmt.Printf("Resource is still used by %d references/n", sr.refCount) }}
最后我們使用這個代理:
func main() { resource := &MyResource{} proxyRef := NewResourceProxy(resource) proxyRef.Use() // 使用資源,引用計數增加 proxyRef.Release() // 釋放一次引用,引用計數減少到0,資源被釋放 // Output: // Resource is used 1 times // Using MyResource // Releasing MyResource}
這個簡單的例子演示了代理在資源管理中的應用,可以根據實際需要添加更多復雜的邏輯,比如錯誤處理、同步控制、日志記錄等。
在程序設計中,代理模式是一種結構型設計模式,它讓我們能提供一個替代品來代表另一個對象,這個替代品控制著對原對象的訪問,可以在訪問原對象前后進行一些額外處理。
通過上邊的示例,我們可以發現代理模式的三個主要角色:
在代碼實際實現時,代理模式其實有多種不同的實現,包括:
這里就不展示更多的代碼了,關鍵是在合適的時機使用恰當的代理模式來解決問題,這需要細細體會。
做個簡單的小結,代理模式就像程序中的一個“中間人”,在不需要直接訪問某個對象,或者直接訪問某個對象不太方便或者不符合需求時,代理模式提供了一個非常靈活的解決方案。
正如本文所探討的,代理模式在網絡通信和程序設計中都扮演著重要的角色。它通過提供一個中間層,增強了系統的安全性、靈活性和可維護性。掌握代理,我們就擁有了在合適的場景下解決問題的一種強大能力。希望本文的討論能對你有一點用處。
本文鏈接:http://www.www897cc.com/showinfo-26-79300-0.html我們一起聊聊什么是正向代理和反向代理
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com