Go语言使用Google Cloud Spanner出现invalid session pool错误的解决方法
问题描述
我使用Spanner库编写了Go代码,创建Spanner客户端时未报错,但执行查询时出现invalid session pool错误,代码及错误日志如下:
代码
package main import ( "log/slog" "log" "fmt" "context" "cloud.google.com/go/spanner" ) func createClient(ctx context.Context, db string) (*spanner.Client, error) { sessionPoolConfig := spanner.SessionPoolConfig{ TrackSessionHandles: true, InactiveTransactionRemovalOptions: spanner.InactiveTransactionRemovalOptions{ ActionOnInactiveTransaction: spanner.WarnAndClose, }, } dataClient, err := spanner.NewClientWithConfig( ctx, db, spanner.ClientConfig{SessionPoolConfig: sessionPoolConfig}, ) if err != nil { slog.Error("failed to create the spanner client", "err", err) return nil, err } defer dataClient.Close() _ = dataClient return dataClient, nil } var dbLink = "projects/PROJECT_NAME/instances/INSTANCE_NAME/databases/DATABASE_NAME" func main() { ctx := context.Background() snapperClient, err := createClient(ctx, dbLink) if err != nil { log.Fatalf("failed to create a spanner client, error=%s", err.Error()) } row, err := spannerClient.Single().ReadRow(ctx, "DATA_TABLE", spanner.Key{THE_KEY}, []string{"THE_COLUMN"}) if err != nil { slog.Error("failed to get the DATA from spanner", "error", err.Error()) return nil, err } ... }
错误日志
2023/11/30 22:40:03 ERROR failed to get the DATA from spanner id=4 error="spanner: code = \"InvalidArgument\", desc = \"invalid session pool\""
请问如何修复这个invalid session pool错误?
解决方案
导致该错误的核心问题有三个,逐一修复即可:
移除
createClient函数内的defer dataClient.Close()
你在创建客户端后立刻通过defer关闭了它,函数返回时客户端已被销毁,后续main函数使用这个已关闭的客户端,就会触发会话池无效的错误。正确做法是将客户端关闭逻辑移到调用方(即main函数):
修改后的createClient函数:func createClient(ctx context.Context, db string) (*spanner.Client, error) { sessionPoolConfig := spanner.SessionPoolConfig{ TrackSessionHandles: true, InactiveTransactionRemovalOptions: spanner.InactiveTransactionRemovalOptions{ ActionOnInactiveTransaction: spanner.WarnAndClose, }, } dataClient, err := spanner.NewClientWithConfig( ctx, db, spanner.ClientConfig{SessionPoolConfig: sessionPoolConfig}, ) if err != nil { slog.Error("failed to create the spanner client", "err", err) return nil, err } // 移除此处的defer Close() return dataClient, nil }在
main函数中添加关闭逻辑:func main() { ctx := context.Background() snapperClient, err := createClient(ctx, dbLink) if err != nil { log.Fatalf("failed to create a spanner client, error=%s", err.Error()) } defer snapperClient.Close() // 在此处添加defer关闭客户端 // 后续查询逻辑... }修正变量名拼写错误
main函数中创建的客户端变量是snapperClient,但查询时误用了spannerClient,需统一变量名:row, err := snapperClient.Single().ReadRow(ctx, "DATA_TABLE", spanner.Key{THE_KEY}, []string{"THE_COLUMN"})修复
main函数的错误返回逻辑main函数的返回类型为func main(),不能返回nil, err,需改为log.Fatal(err)或其他合法的错误处理方式:if err != nil { slog.Error("failed to get the DATA from spanner", "error", err.Error()) log.Fatal(err) }
内容的提问来源于stack exchange,提问作者MLev
相关产品推荐
相关产品推荐

