2015-08-16 21 views
5

Bazı istemcilerde (aşağıya bakın) Go'da yazılan ve "istekleri dışa aktarma" HTTP istekleri olması ve ayrıntıların bir araya getirilmesi/toplanması. kasten yavaş (5 saniye uyur ve daha sonra bir yanıt verir) bir yerel sunucu çalışan yokturHTTP zaman aşımı hataları nasıl işlenir ve golang'da durum kodlarına erişme

{ 
    "Status":"success", 
    "Components":[ 
     {"Id":"foo","Status":200,"Body":"..."}, 
     {"Id":"bar","Status":200,"Body":"..."}, 
     {"Id":"baz","Status":404,"Body":"..."}, 
     ... 
    ] 
} 

:

I'm new to golang and so expect me to be a nOOb and my knowledge to be limited

programın çıktısı şu anda böyle bir şeydir. Ama listelenen başka bir sitem var (aşağıya bakınız), bazen bir hatayı da tetikler (hata yaparsa, o zaman bu iyi olur).

Şu anda sahip olduğum sorun, bu hataların ve özellikle de "zaman aşımı" ile ilgili hataların nasıl en iyi şekilde işleneceğidir; Bunun içinde bir başarısızlığın zaman aşımı mı yoksa başka bir hata mı olduğunu nasıl anlayacağımı bilmiyorum? Şu anda

Her zaman bir battaniye hatası geri almak: (! umarım zaman aşımı yoluyla) http://localhost:8080/pugs genellikle başarısız url olacak

Get http://localhost:8080/pugs: read tcp 127.0.0.1:8080: use of closed network connection 

. Ancak, koddan (aşağıda) görebileceğiniz gibi, hata kodunun bir zaman aşımıyla nasıl ilişkilendirileceğinden ya da yanıtın durum koduna nasıl erişileceğinden emin değilim (Şu anda sadece 404'a ayarlamayı batırıyorum. Açıkçası bu doğru değil - sunucu hata olurdu eğer bir 500 durum kodu gibi bir şey beklemek ve tabii ki geri göndermek toplu yanıtta yansıtmak istiyorum).

Tam kod aşağıda görülebilir. Herhangi bir yardım takdir edildi. Dışarı sonra fana toplu sonuçlar istiyorsanız ve net/http paket size vermiyor belirli zaman aşımı davranış istiyorsanız

package main 

    import (
      "encoding/json" 
      "fmt" 
      "io/ioutil" 
      "net/http" 
      "sync" 
      "time" 
    ) 

    type Component struct { 
      Id string `json:"id"` 
      Url string `json:"url"` 
    } 

    type ComponentsList struct { 
      Components []Component `json:"components"` 
    } 

    type ComponentResponse struct { 
      Id  string 
      Status int 
      Body string 
    } 

    type Result struct { 
      Status  string 
      Components []ComponentResponse 
    } 

    var overallStatus string = "success" 

    func main() { 
      var cr []ComponentResponse 
      var c ComponentsList 

      b := []byte(`{"components":[{"id":"local","url":"http://localhost:8080/pugs"},{"id":"google","url":"http://google.com/"},{"id":"integralist","url":"http://integralist.co.uk/"},{"id":"sloooow","url":"http://stevesouders.com/cuzillion/?c0=hj1hfff30_5_f&t=1439194716962"}]}`) 

      json.Unmarshal(b, &c) 

      var wg sync.WaitGroup 

      timeout := time.Duration(1 * time.Second) 
      client := http.Client{ 
        Timeout: timeout, 
      } 

      for i, v := range c.Components { 
        wg.Add(1) 

        go func(i int, v Component) { 
          defer wg.Done() 

          resp, err := client.Get(v.Url) 

          if err != nil { 
           fmt.Printf("Problem getting the response: %s\n", err) 

           cr = append(cr, ComponentResponse{ 
            v.Id, 
            404, 
            err.Error(), 
           }) 
          } else { 
            defer resp.Body.Close() 
            contents, err := ioutil.ReadAll(resp.Body) 
            if err != nil { 
              fmt.Printf("Problem reading the body: %s\n", err) 
            } 

            cr = append(cr, ComponentResponse{ 
              v.Id, 
              resp.StatusCode, 
              string(contents), 
            }) 
          } 
        }(i, v) 
      } 
      wg.Wait() 

      j, err := json.Marshal(Result{overallStatus, cr}) 
      if err != nil { 
        fmt.Printf("Problem converting to JSON: %s\n", err) 
        return 
      } 

      fmt.Println(string(j)) 
    } 
+0

Büyük olasılıkla ilgisiz için Senin problemin, ama 'cr' ekleyerek bir veri yarış var. Senkronizasyon olmadan aynı değişkeni birden fazla goroutinden yazamazsınız. [Yarış dedektörü] ile (https://blog.golang.org/race-detector) kurmak/koşmak isteyebilirsiniz. –

+0

Yorum için teşekkürler. Bunun yerine kanalları kullanmayı düşüneceğim + o yarış dedektörünü araştırıyorum :-) – Integralist

+1

İstemci çağrısı bir hata döndürürse, tam bir http isteği olmadığından durum kodu yoktur. Bu noktada bir hata ile yapabileceğiniz pek bir şey yoktur, ancak bir istemcide go1.5'te. En sonunda bir net.Error'da daha iyi bir mesaj gönderilir. – JimB

cevap

-1

Git 1.5 sürümünde, ele aldığı hata türü hakkında daha spesifik olmak bu sorunu çözdü. Bu örneği https://github.com/Integralist/Go-Requester/blob/master/requester.go#L38 görürseniz

Yani hata gerçekten bir zaman aşımı ya olmasaydı deşifre etmek hata mesajı için bir normal ifade desenini uygulayabilir olduğumu göreceksiniz

status := checkError(err.Error()) 

func checkError(msg string) int { 
    timeout, _ := regexp.MatchString("Timeout", msg) 

    if timeout { 
     return 408 
    } 

    return 500 
} 
+1

Hata dizelerinde etrafta dolaşmayın * en iyi * inanılmaz derecede kırılgandır; hata dizesi, * herhangi bir API'nin * parçası değildir. ['Net.Error' arayüzü] (https://golang.org/pkg/net/#Error) bunun için" Zaman Aşımı "yöntemini tanımlar. –

+0

@Dave C Yorum için teşekkürler, ancak ne önerdiğinizi bilmiyorum. Client.Get'den geri döndüğüm hata bir dizedir. Yöntemi yok. Yani – Integralist

+0

sorgulamak için hiçbir şey Sadece bir dize değil, bir 'hata'. Sen her şeyi uzağında ama biçimlendirilmiş sonuç dizesi ile 'err.Error()' ile kontrol işlevini çağırarak. Bunun yerine bir tür iddia ve diğer kontroller denemelisiniz. Sadece işe yaramazsa, a) test edilemeyen bir hatayla ilgili bir hata raporu vermelisiniz ve b) çirkin bir çalışma olarak (büyük bir uyarı yorumuyla) * belki de dize içinde grep (ya da test edebileceğiniz bir hata döndürmek için kod çağırıyorsunuz ve bunu akışa bir değişiklik talebi olarak gönderiyoruz). –

1

, o zaman goroutines ve kanalları kullanmak isteyebilirsiniz.

Bu videoyu bugün izledim ve Go'nun eşzamanlılık özelliklerini kullanarak tam olarak bu senaryolardan geçecek. Ayrıca, Rob Pike konuşmacısı oldukça otorite - bunu yapabildiğimden çok daha iyi açıklıyor.

https://www.youtube.com/watch?v=f6kdp27TYZs

+0

downvote, bir saatlik bir video yayınlamak içindir. cevap nerede? – circuitry