2015-08-16 22 views
5

Tôi có một số mã (xem bên dưới) được viết bằng Go, được yêu cầu "yêu cầu HTTP" của người hâm mộ và đối chiếu/tổng hợp lại chi tiết.Cách xử lý lỗi hết thời gian chờ HTTP và truy cập mã trạng thái trong golang

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

Đầu ra của chương trình hiện đang là một cái gì đó như:

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

Có một máy chủ địa phương chạy đó là cố ý chậm (ngủ trong 5 giây và sau đó trả về một phản ứng). Nhưng tôi có các trang web khác được liệt kê (xem mã dưới đây) mà đôi khi kích hoạt một lỗi là tốt (nếu họ lỗi, thì đó là tốt).

Vấn đề tôi có vào lúc này là cách tốt nhất để xử lý các lỗi này và cụ thể là các lỗi liên quan đến "hết thời gian chờ"; trong đó tôi không chắc chắn làm thế nào để nhận ra nếu một thất bại là một thời gian chờ hoặc một số lỗi khác?

Tại thời điểm này tôi nhận được một lỗi chăn lại tất cả các thời gian: (! Hy vọng bởi thời gian chờ)

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

đâu http://localhost:8080/pugs nói chung sẽ là url rằng thất bại. Nhưng như bạn có thể thấy từ mã (bên dưới), tôi không chắc chắn cách xác định mã lỗi có liên quan đến thời gian chờ cũng như cách truy cập mã trạng thái của phản hồi (hiện tại tôi chỉ đặt chăn là 404 nhưng rõ ràng là không đúng - nếu máy chủ bị lỗi, tôi mong đợi một cái gì đó giống như mã trạng thái 500 và rõ ràng là tôi muốn phản ánh điều đó trong phản hồi tổng hợp mà tôi gửi lại).

Có thể xem mã đầy đủ bên dưới. Bất kỳ trợ giúp nào được đánh giá cao.

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

Nhiều khả năng không liên quan đến vấn đề của bạn, nhưng bạn có một cuộc đua dữ liệu phụ thêm vào 'cr'. Bạn không thể viết cùng một biến từ nhiều goroutines mà không đồng bộ hóa. Bạn có thể muốn xây dựng/chạy với [máy dò cuộc đua] (https://blog.golang.org/race-detector). –

+0

Cảm ơn nhận xét. Tôi sẽ xem xét để sử dụng các kênh thay vì + Tôi sẽ điều tra rằng máy dò cuộc đua :-) – Integralist

+1

Nếu cuộc gọi của khách hàng trả về lỗi, không có mã trạng thái, vì không có yêu cầu http hoàn chỉnh. Không có nhiều bạn có thể làm với một lỗi tại thời điểm đó, nhưng trong go1.5 một client.Timeout sẽ ít nhất trả về một thông điệp tốt hơn trong một net.Error. – JimB

Trả lời

-1

The Go 1.5 phát hành giải quyết vấn đề này bằng cách cụ thể hơn về các loại lỗi nó đã xử lý.

Vì vậy, nếu bạn thấy ví dụ này https://github.com/Integralist/Go-Requester/blob/master/requester.go#L38 bạn sẽ thấy rằng tôi có thể áp dụng một mô hình regex để được thông báo lỗi để giải mã nếu lỗi thực sự là một thời gian chờ hay không

status := checkError(err.Error()) 

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

    if timeout { 
     return 408 
    } 

    return 500 
} 
+1

Đừng lúng túng xung quanh trong các chuỗi lỗi tại * tốt nhất * thật đáng kinh ngạc mong manh; chuỗi lỗi là * không * một phần của bất kỳ API nào. Giao diện ['net.Error'] (https://golang.org/pkg/net/#Error) định nghĩa phương thức' Timeout' cho việc này. –

+0

@Dave C cảm ơn cho nhận xét nhưng tôi không chắc chắn về những gì bạn đã đề xuất hoạt động. Lỗi tôi nhận được từ client.Get là một chuỗi. Nó không có phương pháp. Vì vậy, không có gì để truy vấn – Integralist

+0

Nó không chỉ là một chuỗi, nó là một 'lỗi'. Bạn qua tất cả mọi thứ nhưng chuỗi kết quả được định dạng bằng cách gọi hàm kiểm tra của bạn bằng 'err.Error()'. Thay vào đó, bạn nên thử xác nhận loại và các kiểm tra khác. Chỉ khi tất cả những điều đó không hoạt động nếu bạn a) gửi báo cáo lỗi về lỗi không thể kiểm tra và b) như một công việc xấu xí (với nhận xét cảnh báo lớn) * có thể * grep xung quanh trong chuỗi (hoặc thay đổi mã bạn đang gọi để trả lại lỗi có thể kiểm tra và gửi đó dưới dạng yêu cầu thay đổi ngược dòng). –

1

Nếu bạn muốn tắt tiếng thì kết quả tổng hợp và bạn muốn gói thời gian chờ/net cụ thể không mang lại cho bạn, bạn có thể muốn sử dụng goroutines và kênh.

Tôi vừa xem video này hôm nay và nó sẽ hướng dẫn bạn qua chính xác những trường hợp đó bằng cách sử dụng các tính năng tương tranh của Go. Thêm vào đó, diễn giả Rob Pike là người có thẩm quyền - anh ấy giải thích nó tốt hơn nhiều so với tôi có thể.

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

+0

phiếu giảm giá dành cho đăng video dài một giờ. câu trả lời ở đâu? – circuitry

Các vấn đề liên quan