Goでデータベースのタイムアウトとキャンセルを管理する方法

ここでは、主にリクエストのコンテキストを紹介しますが、注意点がいくつかあります。ミドルウェアを使用する場合は、すべてのリクエストを処理する必要があります。これは必要ですか?respのwritetimeoutにも注意してください。それ以外の場合、SQL処理でのリクエストのタイムアウトがwよりも大きい場合、それは基本的に無効です。

 

処理されません、まず条件付きSQLを作成します

メインパッケージ

のインポート(
    " データベース/ SQL " 
    " FMT " 
    " ログ" 
    " ネット/ HTTP " 

    _ " github.com/lib/pq " 

のvarデシベル* sql.DB 

FUNC slowQuery()エラー{ 
    :_、ERR =デシベルを。 Exec(" SELECT pg_sleep(10)" return err 
} 

func main(){ 
    var err error 

    db、err = sql.Open(" postgres "" postgres:// user:pa $$ word @ localhost / example_db" if err!= nil { 
        log.Fatal(err)
    } 

    if err = db.Ping(); err!= nil { 
        log.Fatal(err)
    } 

    mux: = http.NewServeMux()
    mux.HandleFunc(" / " 、exampleHandler)

    log.Println(" Listening ... " 
    err = http.ListenAndServe(" :5000 " 、mux)
     if err!= nil { 
        log.Fatal(err)
    } 
} 

func exampleHandler(w http.ResponseWriter、 r* http.Request){ 
    err: = slowQuery()
     if err!= nil { 
        serverError(w、err)
        return 
    } 

    fmt.Fprintln(w、" OK " 
} 

func serverError(w http.ResponseWriter、err error){ 
    ログ.Printf(" ERROR:%s " 、err.Error())
    http.Error(w、" 申し訳ありませんが、問題が発生しました" 、http.StatusInternalServerError)
}

 

 

いくつかの処理デモ

メインパッケージ

のインポート(
    " 文脈"  // 新しいインポート
    " データベース/ SQL " 
    " FMT " 
    " ログ" 
    " ネット/ HTTP " 
    " 時間"  // 新しいインポート

    _ " github.com/lib/pq " 

のvarデシベル* SQLを。 DB 

func slowQuery(ctx context.Context)error { 
    // 指定されたctxパラメータを親として使用して、// 5秒のタイムアウトで新しい子コンテキストを作成します
     
    ctx、キャンセル:= context.WithTimeout(ctx、time.Second)は
    延期)(キャンセル

    // 最初と子コンテキスト(タイムアウト付き1)を渡し
     // )ExecContext(へのパラメータ。
    _、err:= db.ExecContext(ctx、" SELECT pg_sleep(10)" return err 
} 

... 

func exampleHandler(w http.ResponseWriter、r * http.Request){
     // リクエストコンテキストをslowQuery()に渡すなので、// 親コンテキストとして使用でき 
     ます。
    err:= slowQuery(r.Context())
     if if err!= nil { 
        serverError(w、err)
        return 
    }

    fmt.Fprintln(w、" OK " 
} 

...

 

 

パッケージのメイン

インポート(
    " 文脈" 
    " データベース/ SQL " 
    " エラー"  // 新しいインポート
    " FMT " 
    " ログ" 
    " ネット/ HTTP " 
    " 時間" 

    _ " github.com/lib/pq " 

のvarデシベル* sql.DB 

func slowQuery(ctx context.Context)error { 
    ctx、cancel: = context.WithTimeout(ctx、5 * time.Second)
    defer cancel()

    _、err: = db.ExecContext(ctx、SELECT pg_sleep(10)" // "とのエラーラップ、それをキャンセルする声明...:PQ我々は、取得する場合は、" 
     // 返す前に、コンテキスト・エラーを。
    もし ERR = nilの&& err.Error()==!" PQ:ユーザー要求によるステートメントのキャンセル" {
         return fmt.Errorf(" %w:%v " 、ctx.Err()、err)
    } 

    return err 
} 

... 

func exampleHandler(w http.ResponseWriter、r * http.Request) { 
    err: = slowQuery(r.Context())
     if err!= nil {
         //返されたエラーがcontext.Canceledと等しいかラップするかどうかを確認し、// 等しい場合は 
         警告を記録します。
        スイッチ{
         case errors.Is(err、context.Canceled):
            serverWarning(err)
        default 
            serverError(w、err)
        } 
        return 
    } 

    fmt.Fprintln(w、" OK " 
} 

func serverWarning(err error){ 
    log.Printf (" 警告:%s " 、err.Error())
} 

...

 

 

... 

func main(){ 
    var err error 

    db、err = sql.Open(" postgres "" postgres:// user:pa $$ word @ localhost / example_db " if err!= nil { 
        log.Fatal( ERR)
    } 

    // 空用い、10秒のタイムアウトを有するコンテキストを作成 
     // 親としてcontext.Backgroundを()。
    ctx、cancel:= context.WithTimeout(context.Background()、10 * time.Second)
    defer cancel()

    // 接続プールをテストするときにこれを使用します。
    もしエラー= db.PingContext(ctx); err!= nil { 
        log.Fatal(err)
    } 

    mux: = http.NewServeMux()
    mux.HandleFunc(" / " 、exampleHandler)

    log.Println(" Listening ... " 
    err = http.ListenAndServe(" :5000 " 、mux)
     if err!= nil { 
        log.Fatal(err)
    } 
} 

...

 

ミドルウェア

func setTimeout(next http.Handler)http.Handler {
     return http.HandlerFunc(func(w http.ResponseWriter、r * http.Request){ 
        ctx、cancel: = context.WithTimeout(r.Context()、5 * time。第二)
        )(取り消し延期

        // これは、要求コンテキストであなたの要求のコピーを提供します 
         // 作成した5秒のタイムアウトを新しいコンテキストに変更 
         // 上記の。 
        R = r.WithContext(CTX)
        next.ServeHTTP (w、r)
    })
}

 

 

元の住所

https://www.alexedwards.net/blog/how-to-manage-database-timeouts-and-cancellations-in-go

 

著者は非常に詳細に書いた、内容は難しくありません。

おすすめ

転載: www.cnblogs.com/CherryTab/p/12757886.html