2017-09-15 2 views
1

나는 학습 중이며 외부 패키지에서 패닉을 제대로 처리하는 방법을 이해하려고합니다.외부 패키지에서 비동기 패닉을 복구하는 방법

실행 가능한 예제입니다. 패키지가 doFoo 메서드를 정의한다고 가정 해보십시오. 서버 충돌 할 doFoo의 메소드를 호출

package main 

import (
    "log" 
    "net/http" 

    "sync" 
    "time" 

    "github.com/gorilla/handlers" 
    "github.com/gorilla/mux" 
) 
// Method from External package 
func doFoo() { 
    var wg sync.WaitGroup 
    wg.Add(1) 
    // Do some cool async stuff 
    go func() { 
     time.Sleep(500) 
     wg.Done() 
     panic("Oops !") 
    }() 
} 

func router() *mux.Router { 
    var router = mux.NewRouter().StrictSlash(true) 
    router.HandleFunc("/doFoo", index).Methods("GET") 
    return router 
} 

func main() { 
    log.Fatal(http.ListenAndServe(":8080", handlers.RecoveryHandler()(router()))) 
} 

func index(w http.ResponseWriter, r *http.Request) { 
    defer func() { 
     recover() 
     w.WriteHeader(http.StatusInternalServerError) 
    }() 
    doFoo() 
    w.WriteHeader(http.StatusOK) 
} 

(그것은 예를 위해 여기에 같은 패키지에있는 것), 나는 응용 프로그램이 훼손 상태가 지금이기 때문에 즉, 올바른 동작입니다 주셔서 감사합니다. 충돌이 발생하여 후속 요청이 일부 부하 분산 장치를 통해 다른 프로세스로 전달되도록하는 것이 가장 좋습니다. 하지만 내 api 서버가 여전히 다른 클라이언트에게 서비스를 제공하고 있으며 웹 소켓을 유지 관리하고있을 수도 있습니다. 여기에 500 개의 오류도 반환하려고합니다.

nodejs에서 오는 것은 uncaughtException의 개념에 따라 캡처되지 않은 동기 예외를 처리하는 데 익숙하지 않은데 unhandledRejection은 캡처되지 않은 비동기 예외를 처리하는 데 익숙합니다. 이 두 프로세스 구조는 개발자가 프로그램을 즉시 중단하거나 오류를 기록하고 적절한 http 코드를 반환 한 다음 필요할 경우 정상적으로 종료하도록 선택할 수 있습니다.

제 온라인 연구에서 나는 공포가 예외가 아니고, 특이한 것이 아니라, 당신이 그들에 대해 걱정할 필요가 없다는 많은 리소스를 발견했습니다. 그러나 코드를 작성할 때 공포감을 일으키는 것은 실제로 매우 쉽습니다. 자신의 도서관이 당황하지 않도록하는 것은 개발자의 몫입니다. 인간의 요소는 여기에 100 % 참여했습니다.

이것은 궁금해합니다. 모든 패키지 의존성을 포함하여 사용하려는 모든 단일 패키지의 전체 코드베이스를 감사해야합니까?? 내 모든 서버를 다운 시켜서 내 사용자의 경험을 망칠 수있는 일부 외부 패키지에서 누락 복구를 방지 할 수단이 없기 때문에?

또는 비동기 패닉이 라이브러리 코드에서 발생할 때 정상적으로 실패 할 수 있다는 것을 모르는 전략이 있습니까?

1.8 이후로 정상 종료가 확인되었지만 내 프로그램이 이미 충돌했기 때문에 사용할 수 없습니다. https://golang.org/pkg/net/http/#Server.Shutdown

고릴라 복구 핸들러가 있지만, 이것은 동기 패닉에 대해서만 보호합니다. http://www.gorillatoolkit.org/pkg/handlers#RecoveryHandler

업데이트 :
내가 패닉이 예외가 아니라는 것을 알고 있습니다. 그 질문에 대답하지 않는 재시험, 공포와 예외는이 질문에 관한 것이 아닙니다. 이 질문은 전체 패키지 트리의 모든 단일 행을 개발자에게 읽지 않아도 언어가 경계를 강화하기 위해 제공 할 수있는 도구를 이해하는 것입니다. 그것이 언어에서 가능하지 않다면 그 말이 유효한 대답이라는 것을 나타냅니다. 그것이 맞는지 아닌지 나는 모른다.

+0

간단히 말해서, 당신은하지 않습니다. 예기치 않은 패닉이 응용 프로그램을 중단시키고 예상되는 코스가 다시 시작됩니다. – JimB

답변

1

패닉은 예외가 아닙니다. 그들을 예외로 취급하지 마십시오. 그러면 괜찮을 것입니다.

일단 가장 중요한 패키지 API는 그들이 항상 특정 매우 드문 경우를 제외하고 오류를 반환해야합니다 당황해서는 안, 그리고 그들은 분명히 (regexp.MustCompile이 좋은 예이다를 때 왜 당황 수있는 문서화되어야한다 공황 상태에 빠질 수있는 것들).오류가 발생했을 때 패닉이 발생하는 패키지는 이 매우이므로 좋지 않습니다. 사용하지 마십시오.

경계 검사를 수행하는 경우 nil 포인터 등을 액세스하지 않도록주의하십시오. 패닉에 대해 걱정할 필요가 없습니다.

goroutine에서 패닉을 복구하는 경우 goroutine에 자체 복구 핸들러가 없으면 수행 할 수 없습니다.

제 3 자 라이브러리에서 goroutine을 사용하는 경우 해당 라이브러리를 사용하지 마십시오! 오류가 발생하여 패닉 상태에 빠질 정도로 게으르다면 왜 코드를 사용하고 있습니까? 다른 광산이 무엇을 가지고 있는지 누가 압니까?

goroutine이 자신의 코드 인 경우 패닉 상태의 항목을 제거한 다음 필요한 경우 예방할 수없는 항목을 복구 핸들러에 추가하십시오.

+0

그렇다면 각 하위 패키지를 포함하여 각 패키지를 감사해야합니까? 이 언어는 패키지가 당황하지 않도록 보장 해주지 않습니다. –

+3

제대로 작성되지 않은 스케치 패키지를 사용하고 있다면 그렇습니다. 그들이 쓰는 언어에 관계없이 감사를 원할 것입니다. 실제 사용에서는 좋은 품질의 대중적인 패키지를 사용하고 있습니다. 생각보다 문제가 적다는 것을 알게 될 것입니다. –

+0

일반적인 프로젝트의 종속성은 10 - 20+이며, 각 프로젝트는 5 - 10 개 이상의 종속성을 가질 수 있습니다. 우리는 100,000 라인의 오픈 소스 코드를 사용하고 있습니다. 이제는 서버가 무작위로 충돌하지 않고 모든 사용자를 차단할 수 있는지 고객에게 묻습니다. nodejs를 사용하면 예라고 말할 수 있습니다. 프로젝트에서 Go를 사용할 때 나는 무엇을 대답합니까? 이것이 바로이 질문에 관한 것입니다. 회피하는 모든 응답은 산만합니다. 중간 규모의 서버 측 프로젝트에 대해 신뢰할 수 있는지 확인하십시오. –

관련 문제