您好,登錄后才能下訂單哦!
Golang實(shí)現(xiàn)API網(wǎng)關(guān)的方法是什么?這個(gè)問題可能是我們?nèi)粘W(xué)習(xí)或工作經(jīng)常見到的。希望通過(guò)這個(gè)問題能讓你收獲頗深。下面是小編給大家?guī)?lái)的參考內(nèi)容,讓我們一起來(lái)看看吧!
在最近的一個(gè)項(xiàng)目中,采用了微服務(wù)架構(gòu)-go-kit
進(jìn)行后端的開發(fā)。在微服務(wù)架構(gòu)風(fēng)格中,一個(gè)大應(yīng)用被拆分成為了多個(gè)小的服務(wù)系統(tǒng)提供出來(lái),這些小的系統(tǒng)他們可以自成體系,也就是說(shuō)這些小系統(tǒng)可以擁有自己的數(shù)據(jù)庫(kù),框架甚至語(yǔ)言等,因此我們需要設(shè)計(jì)一個(gè)API 網(wǎng)關(guān)(API Gataway),其實(shí)網(wǎng)上已經(jīng)有較多現(xiàn)成的實(shí)現(xiàn)框架,但是本項(xiàng)目的需求是比較簡(jiǎn)單的,因此將使用Golang
自行實(shí)現(xiàn)。
API網(wǎng)關(guān)是一個(gè)服務(wù)器,是系統(tǒng)的唯一入口。從面向?qū)ο笤O(shè)計(jì)的角度看,它與外觀模式類似。API網(wǎng)關(guān)封裝了系統(tǒng)內(nèi)部架構(gòu),為每個(gè)客戶端提供一個(gè)定制的API。它可能還具有其它職責(zé),如身份驗(yàn)證、監(jiān)控、負(fù)載均衡、緩存、請(qǐng)求分片與管理、靜態(tài)響應(yīng)處理。
用于實(shí)現(xiàn)API網(wǎng)關(guān)的技術(shù)有很多,大致分為這么幾類:
Nginx
、Haproxy
、……Netty
、Servlet
、……Spring Cloud Gateway
、Zuul
、Zuul2
、……API網(wǎng)關(guān)最基本的功能就是反向代理。其實(shí)現(xiàn)方式有很多,本文將基于標(biāo)準(zhǔn)庫(kù)net/http/httputil
包中的ReverseProxy
類型來(lái)實(shí)現(xiàn)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的反向代理。反向代理的實(shí)現(xiàn)主要涉及到func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy
和type ReverseProxy
。
func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy
// NewSingleHostReverseProxy returns a new ReverseProxy that routes// URLs to the scheme, host, and base path provided in target. If the// target's path is "/base" and the incoming request was for "/dir",// the target request will be for /base/dir.// NewSingleHostReverseProxy does not rewrite the Host header.// To rewrite Host headers, use ReverseProxy directly with a custom// Director policy.func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy { targetQuery := target.RawQuery director := func(req *http.Request) { req.URL.Scheme = target.Scheme req.URL.Host = target.Host req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path) if targetQuery == "" || req.URL.RawQuery == "" { req.URL.RawQuery = targetQuery + req.URL.RawQuery } else { req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery } if _, ok := req.Header["User-Agent"]; !ok { // explicitly disable User-Agent so it's not set to default value req.Header.Set("User-Agent", "") } } return &ReverseProxy{Director: director}}
NewSingleHostReverseProxy
返回一個(gè)新的ReverseProxy
,將URLs
請(qǐng)求路由到targe
的指定的scheme
, host
, base path
。
// ReverseProxy is an HTTP Handler that takes an incoming request and// sends it to another server, proxying the response back to the// client.type ReverseProxy struct { // Director must be a function which modifies // the request into a new request to be sent // using Transport. Its response is then copied // back to the original client unmodified. // Director must not access the provided Request // after returning. Director func(*http.Request) Transport http.RoundTripper FlushInterval time.Duration ErrorLog *log.Logger BufferPool BufferPool // ModifyResponse is an optional function that modifies the // Response from the backend. It is called if the backend // returns a response at all, with any HTTP status code. // If the backend is unreachable, the optional ErrorHandler is // called without any call to ModifyResponse. // // If ModifyResponse returns an error, ErrorHandler is called // with its error value. If ErrorHandler is nil, its default // implementation is used. ModifyResponse func(*http.Response) error ErrorHandler func(http.ResponseWriter, *http.Request, error)}
ReverseProxy
類型有兩個(gè)重要的屬性,分別是Director
和ModifyResponse
,這兩個(gè)屬性都是函數(shù)類型,在接收到客戶端請(qǐng)求時(shí),ServeHTTP
函數(shù)首先調(diào)用Director
函數(shù)對(duì)接受到的請(qǐng)求體進(jìn)行修改,例如修改請(qǐng)求的目標(biāo)地址、請(qǐng)求頭等;然后使用修改后的請(qǐng)求體發(fā)起新的請(qǐng)求,接收到響應(yīng)后,調(diào)用ModifyResponse
函數(shù)對(duì)響應(yīng)進(jìn)行修改,最后將修改后的響應(yīng)體拷貝并響應(yīng)給客戶端,這樣就實(shí)現(xiàn)了反向代理的整個(gè)流程。
在NewSingleHostReverseProxy
中源碼已經(jīng)對(duì)傳入的URLs
進(jìn)行解析并且完成了Director
的修改,我們只需要調(diào)用NewSingleHostReverseProxy
函數(shù)并且傳入目標(biāo)服務(wù)器的URL即可,一個(gè)簡(jiǎn)單的反向代理就完成了啦。
實(shí)例代碼只涉及微服務(wù)中
user
與auth
模塊,可以根據(jù)實(shí)際需求自行修改部分
package mainimport ( "fmt" "log" "net/http" "net/http/httputil" "net/url" "strings")type handle struct { host string port string}type Service struct { auth *handle user *handle}func (this *Service) ServeHTTP(w http.ResponseWriter, r *http.Request) { var remote *url.URL if strings.Contains(r.RequestURI, "api/auth") { remote, _ = url.Parse("http://" + this.auth.host + ":" + this.auth.port) } else if strings.Contains(r.RequestURI, "api/user") { remote, _ = url.Parse("http://" + this.user.host + ":" + this.user.port) } else { fmt.Fprintf(w, "404 Not Found") return } proxy := httputil.NewSingleHostReverseProxy(remote) proxy.ServeHTTP(w, r)}func startServer() { // 注冊(cè)被代理的服務(wù)器 (host, port) service := &Service{ auth: &handle{host: "127.0.0.1", port: "8081"}, user: &handle{host: "127.0.0.1", port: "8082"}, } err := http.ListenAndServe(":8888", service) if err != nil { log.Fatalln("ListenAndServe: ", err) }}func main() { startServer()}
感謝各位的閱讀!看完上述內(nèi)容,你們對(duì)Golang實(shí)現(xiàn)API網(wǎng)關(guān)的方法是什么大概了解了嗎?希望文章內(nèi)容對(duì)大家有所幫助。如果想了解更多相關(guān)文章內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。