1. 程式人生 > >基於gin的golang web開發:服務間呼叫

基於gin的golang web開發:服務間呼叫

微服務開發中服務間呼叫的主流方式有兩種HTTP、RPC,HTTP相對來說比較簡單。本文將使用 ```Resty``` 包來實現基於HTTP的微服務呼叫。 ### Resty簡介 ```Resty``` 是一個簡單的HTTP和REST客戶端工具包,簡單是指使用上非常簡單。Resty在使用簡單的基礎上提供了非常強大的功能,涉及到HTTP客戶端的方方面面,可以滿足我們日常開發使用的大部分需求。 go get安裝 ``` go get github.com/go-resty/resty/v2 ``` ### 使用Resty提交HTTP請求 ```golang client := resty.New() resp, err := client.R(). Get("https://httpbin.org/get") resp, err := client.R(). SetQueryParams(map[string]string{ "page_no": "1", "limit": "20", "sort":"name", "order": "asc", "random":strconv.FormatInt(time.Now().Unix(), 10), }). SetHeader("Accept", "application/json"). SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F"). Get("/search_result") resp, err := client.R(). SetQueryString("productId=232&template=fresh-sample&cat=resty&source=google&kw=buy a lot more"). SetHeader("Accept", "application/json"). SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F"). Get("/show_product") resp, err := client.R(). SetResult(AuthToken{}). ForceContentType("application/json"). Get("v2/alpine/manifests/latest") ``` 以上程式碼演示了HTTP GET請求,```Resty```提供```SetQueryParams```方法設定請求的查詢字串,使用```SetQueryParams``` 方法我們可以動態的修改請求引數。```SetQueryString```也可以設定請求的查詢字串,如果引數中有變數的話,需要拼接字串。```SetHeader```設定請求的HTTP頭,以上程式碼設定了```Accept```屬性。```SetAuthToken```設定授權資訊,本質上還是設定HTTP頭,以上例子中HTTP頭會附加```Authorization: Bearer BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F```授權屬性。```SetResult```設定返回值的型別,Resty自動解析json通過```resp.Result().(*AuthToken)```獲取。 下面來看一下POST請求 ```golang client := resty.New() resp, err := client.R(). SetBody(User{Username: "testuser", Password: "testpass"}). SetResult(&AuthSuccess{}). SetError(&AuthError{}). Post("https://myapp.com/login") resp, err := client.R(). SetBody(map[string]interface{}{"username": "testuser", "password": "testpass"}). SetResult(&AuthSuccess{}). SetError(&AuthError{}). Post("https://myapp.com/login") resp, err := client.R(). SetHeader("Content-Type", "application/json"). SetBody(`{"username":"testuser", "password":"testpass"}`). SetResult(&AuthSuccess{}). Post("https://myapp.com/login") resp, err := client.R(). SetHeader("Content-Type", "application/json"). SetBody([]byte(`{"username":"testuser", "password":"testpass"}`)). SetResult(&AuthSuccess{}). Post("https://myapp.com/login") ``` POST請求的程式碼和GET請求類似,只是最後呼叫了```Post```方法。POST請求可以附帶BODY,程式碼中使用```SetBody```方法設定POST BODY。```SetBody```引數型別為結構體或```map[string]interface{}```時,```Resty```自動附加HTTP頭```Content-Type: application/json```,當引數為string或[]byte型別時由於很難推斷內容的型別,所以需要手動設定```Content-Type```請求頭。```SetBody```還支援其他型別的引數,例如上傳檔案時可能會用到的io.Reader。```SetError```設定HTTP狀態碼為4XX或5XX等錯誤時返回的資料型別。 ```Resty``` 也提供了發起其他請求的方法,發起```PUT```請求和發起```POST```請求程式碼上只需要把最後的```Post```改成```Put```方法。其他沒有差別,一樣可以呼叫```SetBody```、```SetError```等方法。程式碼如下 ```golang client := resty.New() resp, err := client.R(). SetBody(Article{ Title: "go-resty", Content: "This is my article content, oh ya!", Author: "Jeevanandam M", Tags: []string{"article", "sample", "resty"}, }). SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD"). SetError(&Error{}). Put("https://myapp.com/article/1234") ``` PATCH,DELETE,HEAD,OPTIONS請求也是一樣的,```Resty```為我們提供了一致的方式發起不同請求。 ### 高階應用 #### 代理 使用```Resty```作為HTTP客戶端使用的話,新增代理似乎是一個常見的需求。```Resty```提供了```SetProxy```方法為請求新增代理,還可以呼叫```RemoveProxy```移除代理。程式碼如下: ``` client := resty.New() client.SetProxy("http://proxyserver:8888") client.RemoveProxy() ``` #### 重試 ```golang client := resty.New() client. SetRetryCount(3). SetRetryWaitTime(5 * time.Second). SetRetryMaxWaitTime(20 * time.Second). SetRetryAfter(func(client *resty.Client, resp *resty.Response) (time.Duration, error) { return 0, errors.New("quota exceeded") }) client.AddRetryCondition( func(r *resty.Response) (bool, error) { return r.StatusCode() == http.StatusTooManyRequests }, ) ``` 由於網路抖動帶來的介面穩定性的問題```Resty```提供了重試功能來解決。以上程式碼我們可以看到```SetRetryCount```設定重試次數,```SetRetryWaitTime```和```SetRetryMaxWaitTime```設定等待時間。```SetRetryAfter```是一個重試後的回撥方法。除此之外還可以呼叫```AddRetryCondition```設定重試的條件。 #### 中介軟體 ```Resty``` 提供了和Gin類似的中介軟體特性。```OnBeforeRequest```和```OnAfterResponse```回撥方法,可以在請求之前和響應之後加入自定義邏輯。引數包含了```resty.Client```和當前請求的```resty.Request```物件。成功時返回```nil```,失敗時返回```error```物件。 ```golang client := resty.New() client.OnBeforeRequest(func(c *resty.Client, req *resty.Request) error { return nil }) client.OnAfterResponse(func(c *resty.Client, resp *resty.Response) error { return nil }) ``` 文章出處:[基於gin的golang web開發:服務間呼叫][source] [source]: https://www.huaface.com/artic