簡體   English   中英

寫入響應作者的內容表現出不穩定的行為

[英]Content written to response writer shows erratic behaviour

文件:main.go

import (
  "github.com/gorilla/mux"
  )
  
func setupRouting(pBus *bus.Bus) *mux.Router {

    log.Debug("Setting up routing")

    r := mux.NewRouter()

    pInvoiceHandler := handlers.NewInvoiceHandler(pBus)

    postRouter.HandleFunc("/invoice", pInvoiceHandler.HandleInvoiceGenerationRequest)


    return r
}

main() {
    pRouter := setupRouting(pBus)
    
    s := &http.Server{
        Addr:         address,
        Handler:      pRouter,
        IdleTimeout:  time.Duration(idlTimeout) * time.Second,
        ReadTimeout:  time.Duration(rdTimeout) * time.Second,
        WriteTimeout: time.Duration(wrtTimeout) * time.Second,
    }
}

文件:InvoiceGenerationHandler.go

func (ih *InvoiceHandler) HandleInvoiceGenerationRequest(rw http.ResponseWriter, pReq *http.Request) {

    log.Info("Handling invoice generation request")

    query := pReq.URL.Query()
    resourceGrp := query.Get("rGrp")

    if resourceGrp == "" {
        http.Error(rw, "Invalid URL, rGrp parameter should be present in the URL ", http.StatusBadRequest)
        return
    }

    pSliceCostDetailsCtx, err := ih.pApiLoadTesting.CalculateCost(resourceGrp)

    if err != nil {
        log.Error("Could not calculate cost :", err.Error())
        http.Error(rw, err.Error(), http.StatusInternalServerError)
        return
    }

    pResponseJson, err := json.Marshal(pSliceCostDetailsCtx)

    if err != nil {
        log.Error("Could not convert price context slice to json: ", err.Error())
        http.Error(rw, "Could not generate cost response", http.StatusInternalServerError)
        log.Error(pResponseJson)
        return
    }

    rw.Write(pResponseJson)
}

文件:apiloadtestpricing.go

type ApiLoadTestPricing struct {
    mpHttpClient *http.Client
}

func NewApiLoadTesting() *ApiLoadTestPricing {
    var pHttpClient = &http.Client{
        Timeout: time.Second * 120,
    }
    return &ApiLoadTestPricing{pHttpClient}
}

func getBearerToken(pHttpClient *http.Client, microsoftTokenEndpoint string) (string, error) {

    v := url.Values{}
    v.Set("grant_type", "client_credentials")
    v.Set("client_id", "******************************")
    v.Set("client_secret", "**************************")

    v.Set("resource", "https://management.core.windows.net")

    params := strings.NewReader(v.Encode())

    req, err := http.NewRequest(http.MethodPost, microsoftTokenEndpoint, params)

    if err != nil {
        log.Error("Could not create a new request")
        log.Error("Encountered error: ", err.Error())
        return "", err
    }

    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    req.Header.Set("Host", "login.microsoftonline.com")

    resp, err := pHttpClient.Do(req)

    if err != nil {
        log.Error("Could not get token from microsoft token endpoint ", microsoftTokenEndpoint)
        log.Error("Encountered error: ", err.Error())
        return "", err
    }
    
    /* More Code here not shown */
}

func getCostFromAzureCostManagement(pHttpClient *http.Client, bearerToken string, resourcegroup string) (*[]models.CostDetailsContext, error) {

    log.Info("Getting Cost from Azure")

    url := "https://management.azure.com/subscriptions/6a877c8f-4ca3-4135-9a0c-8e92db2384b4/resourceGroups/" + resourcegroup + "/providers/Microsoft.CostManagement/query?api-version=2021-10-01"
    postBody := `{
                "type": "Usage",
                "timeframe": "MonthToDate",
                "dataset": {
                  "granularity": "Daily",
                  "aggregation": {
                   "totalCost": {
                      "name": "PreTaxCost",
                      "function": "Sum"
                    }
                  },
                 "grouping": [
                    {
                     "type": "Dimension",
                      "name": "resourceGroup"
                    }
                  ]
                }
              }`

    req, err := http.NewRequest(http.MethodPost, url, strings.NewReader(postBody))
    if err != nil {
        panic(err)
    }
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("Authorization", bearerToken)

    resp, err := pHttpClient.Do(req)
    
    /* More Code here not shown */
}

func (pPrice *ApiLoadTestPricing) CalculateCost(rGrp string) (*[]models.CostDetailsContext, error) {

    log.Info("Calculating cost from azure for resource group: ", rGrp)

    token, err := getBearerToken(pPrice.mpHttpClient, "https://login.microsoftonline.com/7a9376d4-7c43-480f-82ba-a090647f651d/oauth2/token")

    if err != nil {
        log.Error("Cost calculation has failed because proper bearer token was not present")
        return nil, err
    }

    pSliceCostDetailsContext, err := getCostFromAzureCostManagement(pPrice.mpHttpClient, "Bearer "+token, rGrp)

    return pSliceCostDetailsContext, err
}

問題陳述:

我在 golang 中編寫了一個小的 API,它做了兩件事:1. 從 azure 活動目錄獲取 Bearer 令牌 2. 調用 Microsoft 成本管理 API 以獲取資源組 cost

問題:案例 1:調用 getBearerToken 和 getCostFromAzureCostManagement 時。 在 InvoiceGenerationHandler.go 中寫入響應編寫器的響應有時會到達,有時不會到達客戶端。

情況 2:當僅調用 getBearerToken 並返回令牌字符串時,它會在每次寫入時到達客戶端。

筆記:

  1. getBearerToken 和 getCostFromAzureCostManagement 都對請求使用相同的 http 客戶端
  2. gorilla mux 用於路由

我做了什么?

  1. 嘗試注釋掉 CalculateCost 代碼 - 響應編寫器有效。
  2. 嘗試注釋掉 getCostFromAzureCostManagement - responsewriter 工作
  3. 嘗試了他們兩個都沒有注釋-reponsewriter 不起作用
  4. 閱讀共享 httpclient 的可能問題並嘗試以下代碼https://github.com/hashicorp/go-cleanhttp - Responsewriter 不起作用。

我被困在這個問題上並且已經沒有想法了,有人可以幫我調試一下嗎?

嘗試增加超時。

IdleTimeout:  60 * time.Second,
ReadTimeout:  60* time.Second,
WriteTimeout: 60* time.Second,

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM