>백엔드 개발 >Golang >응답 반환 후 Go HTTP 서버를 정상적으로 종료하는 방법은 무엇입니까?

응답 반환 후 Go HTTP 서버를 정상적으로 종료하는 방법은 무엇입니까?

DDD
DDD원래의
2024-10-28 19:12:29225검색

How to Gracefully Shut Down a Go HTTP Server After Returning a Response?

응답 반환 후 HTTP 서버 종료

이 시나리오에서는 Instagram API와 상호 작용하는 Go 명령줄 봇을 구축했습니다. 액세스 토큰을 얻으려면 로컬 HTTP 서버를 시작하여 리디렉션 URI를 캡처합니다. 그러나 액세스 토큰을 검색한 후 서버를 수동으로 종료하려고 시도하는 동안 문제가 발생합니다.

문제:

종료 시 "서버가 닫혔습니다" 및 "잘못된 메모리 주소" 오류가 발생합니다. 서버

분석:

발생하는 오류는 모든 연결이 정상적으로 종료되기 전에 HTTP 서버가 조기에 종료되고 있음을 나타냅니다. 이는 HTTP 처리기 및 서버 종료 프로세스의 비동기 동작으로 인해 발생할 수 있습니다.

해결 방법 1: Context.WithCancel 사용:

context.WithCancel을 사용하여 취소할 수 있는 컨텍스트를 생성하는 것을 고려하세요. 액세스 토큰을 검색할 때. 이 컨텍스트를 HTTP 핸들러에 전달하고 CancelFunc를 사용하여 컨텍스트가 닫힐 때 서버를 정상적으로 종료합니다.

<code class="go">package main

import (
    "context"
    "io"
    "log"
    "net/http"
)

func main() {
    ctx, cancel := context.WithCancel(context.Background())

    http.HandleFunc("/quit", func(w http.ResponseWriter, r *http.Request) {
        io.WriteString(w, "Bye\n")
        cancel()
    })
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        io.WriteString(w, "Hi\n")
    })

    srv := &http.Server{Addr: ":8080"}
    go func() {
        err := srv.ListenAndServe()
        if err != http.ErrServerClosed {
            log.Println(err)
        }
    }()

    <-ctx.Done()

    err := srv.Shutdown(context.Background())
    if err != nil {
        log.Println(err)
    }

    log.Println("done.")
}</code>

해결책 2: 여러 기능에 걸쳐 동일한 컨텍스트 사용:

다음을 사용할 수도 있습니다. 여러 HTTP 핸들러와 기본 함수에 동일한 컨텍스트를 적용하여 서버가 종료되어야 할 때 모든 함수에 알림이 전달되도록 합니다.

<code class="go">package main

import (
    "context"
    "io"
    "log"
    "net/http"
)

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        io.WriteString(w, "Hi\n")
    })
    http.HandleFunc("/quit", func(w http.ResponseWriter, r *http.Request) {
        io.WriteString(w, "Bye\n")
        cancel()
    })
    srv := &http.Server{Addr: ":8080"}
    go func() {
        if err := srv.ListenAndServe(); err != nil {
            log.Printf("Httpserver: ListenAndServe() error: %s", err)
        }
    }()
    <-ctx.Done()

    if err := srv.Shutdown(ctx); err != nil && err != context.Canceled {
        log.Println(err)
    }
    log.Println("done.")
}</code>

결론:

context.WithCancel을 사용하거나 여러 기능에서 동일한 컨텍스트를 사용하면 모든 연결이 닫힌 후 HTTP 서버가 정상적으로 종료되도록 할 수 있습니다. 이렇게 하면 현재 발생하는 오류를 방지할 수 있습니다.

위 내용은 응답 반환 후 Go HTTP 서버를 정상적으로 종료하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.