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

陳巨集博發表於2020-12-09

微服務開發中服務間呼叫的主流方式有兩種HTTP、RPC,HTTP相對來說比較簡單。本文將使用 Resty 包來實現基於HTTP的微服務呼叫。

Resty簡介

Resty 是一個簡單的HTTP和REST客戶端工具包,簡單是指使用上非常簡單。Resty在使用簡單的基礎上提供了非常強大的功能,涉及到HTTP客戶端的方方面面,可以滿足我們日常開發使用的大部分需求。

go get安裝

go get github.com/go-resty/resty/v2

使用Resty提交HTTP請求

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請求

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方法。其他沒有差別,一樣可以呼叫SetBodySetError等方法。程式碼如下

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()

重試

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設定重試次數,SetRetryWaitTimeSetRetryMaxWaitTime設定等待時間。SetRetryAfter是一個重試後的回撥方法。除此之外還可以呼叫AddRetryCondition設定重試的條件。

中介軟體

Resty 提供了和Gin類似的中介軟體特性。OnBeforeRequestOnAfterResponse回撥方法,可以在請求之前和響應之後加入自定義邏輯。引數包含了resty.Client和當前請求的resty.Request物件。成功時返回nil,失敗時返回error物件。

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開發:服務間呼叫

相關文章