From 6cc89e2aae6d5ea00bcd2613b8f2f00541e4f5e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=96=87=E9=9D=99?= <1319697849@qq.com> Date: Fri, 6 Jun 2025 14:17:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E4=B8=BAredis?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 ++ c2c.http | 8 +-- conf/config.yaml | 7 +++ global/setting.go | 1 + main.go | 7 +++ pkg/database/redis.go | 98 +++++++++++++++++++++++++++++++++++++ pkg/setting/section.go | 8 +++ service/speechNlu/domain.go | 7 ++- service/speechNlu/redis.go | 63 ------------------------ service/speechNlu/speech.go | 25 +++++----- 10 files changed, 148 insertions(+), 80 deletions(-) create mode 100644 pkg/database/redis.go delete mode 100644 service/speechNlu/redis.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 6db64cf..3d00ccd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ # 更新日志 +## [0.0.1-beta.3] - 2025.6.6 +### Changed +- 更改为redis存储sessionId + ## [0.0.1-beta.2] - 2025.5.29 ### Changed - 补充诗词解析兜底 diff --git a/c2c.http b/c2c.http index 69f82db..2236832 100644 --- a/c2c.http +++ b/c2c.http @@ -14,7 +14,7 @@ Content-Type: application/json "trafficParameter": "mode=childxxx;macWifi=28b77c218ed1;mid=10f05;vender=7e000025;macVoice=testyuntiancloud;ver=3.0;scenario=smarthome;filterName=nlu;req_nlu_length=1;returnType=json;fullDuplex=true;appendLength=1;additionalService=geli_nlu2;version=0.5;filterUrl=https://testnlu.gree.com:443/semantic/unisoundc2c/querys;" }, "nluRet": { - "text": "设一个昨天5点的闹钟" + "text": "今天天气" }, "postProc": {} } @@ -29,11 +29,11 @@ Content-Type: application/json "common": { "remoteIP": "14.215.222.17", "requestId": "1234568123123118129", - "trafficParameter": "ver=3.0;scenario=smarthome;filterName=nlu2;req_nlu_length=2;returnType=json;fullDuplex=true;appendLength=1;additionalService=geli_nlu;mid=11011;version=0.5;macWifi=28b77c23817b1234111111;macVoice=28b77c23817b1234111111" + "trafficParameter": "ver=3.0;scenario=smarthome;filterName=nlu2;req_nlu_length=2;returnType=json;fullDuplex=true;appendLength=1;additionalService=geli_nlu;mid=11011;version=0.5;macWifi=28b77c23817b1234;macVoice=28b77c23817b1234" }, "nluRet": { "asr_recongize": "", - "text": "设置一个昨天5点的闹钟" + "text": "白日依山尽的下一句是什么" } }, "version": "v0" @@ -55,7 +55,7 @@ Content-Type: application/json "trafficParameter": "mode=childxx;macWifi=ece154a73d38;mid=11011;macVoice=testyuntiancloud;ver=3.0;scenario=smarthome;filterName=nlu;req_nlu_length=1;returnType=json;fullDuplex=true;appendLength=1;additionalService=geli_nlu2;version=0.5;filterUrl=https://testnlu.gree.com:443/semantic/unisoundc2c/querys;" }, "nluRet": { - "text": "设置一个昨天5点的闹钟" + "text": "明天空气质量多少" }, "postProc": {} } diff --git a/conf/config.yaml b/conf/config.yaml index 8df12d8..97a1945 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -32,6 +32,13 @@ Device: #举例 DB: Dsn: root:123456@tcp(172.28.124.105:3306)/chatroom?charset=utf8 +Redis: + Host: 172.28.124.110 + Port: 6379 + Username: + Password: 123456 + Dbname: 1 + Speech: ProductId: 279629895 Apikey : 0c74988953dd4ed4bf31955527802cf3 diff --git a/global/setting.go b/global/setting.go index 64bff79..cef38b3 100644 --- a/global/setting.go +++ b/global/setting.go @@ -22,4 +22,5 @@ var ( TencentGwSetting *setting.TencentGwSetting SpeechSetting *setting.SpeechSettings RabbitMqSetting *setting.RabbitMqSettings + RedisSetting *setting.RedisSettings ) diff --git a/main.go b/main.go index fb0cb64..a55df3b 100644 --- a/main.go +++ b/main.go @@ -15,6 +15,7 @@ import ( "os/signal" "runtime" "speech-nlu-parse/middleware" + "speech-nlu-parse/pkg/database" "speech-nlu-parse/pkg/proto" "speech-nlu-parse/service" "speech-nlu-parse/service/speechNlu" @@ -107,6 +108,8 @@ func main() { } }() + database.InitRedis() + // 初始化 gRPC lis, err := net.Listen("tcp", fmt.Sprintf(":%d", global.ServerSetting.Port)) if err != nil { @@ -226,6 +229,10 @@ func setupSetting() error { if err != nil { return err } + err = s.ReadSection("Redis", &global.RedisSetting) + if err != nil { + return err + } consulUrlParse, err := url.Parse(consulUrl) if err != nil { diff --git a/pkg/database/redis.go b/pkg/database/redis.go new file mode 100644 index 0000000..bf711aa --- /dev/null +++ b/pkg/database/redis.go @@ -0,0 +1,98 @@ +package database + +import ( + "context" + "fmt" + "github.com/go-redis/redis/v8" + "log" + "speech-nlu-parse/global" + "time" +) + +var redisClient *redis.Client + +// 初始化 Redis 连接 +func InitRedis() { + redisClient = redis.NewClient(&redis.Options{ + Addr: fmt.Sprintf("%s:%s", global.RedisSetting.Host, global.RedisSetting.Port), + Username: global.RedisSetting.Username, + Password: global.RedisSetting.Password, + DB: global.RedisSetting.Dbname, + PoolSize: 100, + PoolTimeout: 2 * time.Second, + }) + + if err := redisClient.Ping(context.Background()).Err(); err != nil { + global.Logger.Errorf("Redis连接失败: %v", err) + return + } +} + +// 更新会话(首次创建或续期) +func UpdateSession(mac, sessionId string) { //, expiration time.Duration + ctx := context.Background() + key := getSessionKey(mac) + //log.Println("更新会话") + //log.Println(key, sessionId) + + // 直接设置键值并指定过期时间 + err := redisClient.Set(ctx, key, sessionId, time.Minute*10).Err() + if err != nil { + global.Logger.Errorf("会话更新失败 (MAC: %s): %v", mac, err) + } +} + +func getSessionKey(mac string) string { + return fmt.Sprintf("session:%s", mac) +} + +// GetSession 根据 MAC 地址查询对应的 sessionId +func GetSession(mac string) (string, error) { + ctx := context.Background() + key := getSessionKey(mac) + + // 从 Redis 获取 sessionId + sessionId, err := redisClient.Get(ctx, key).Result() + if err != nil { + if err == redis.Nil { + // Key 不存在(不是错误,是正常情况) + return "", nil + } + // 其他错误(如连接问题) + global.Logger.Errorf("查询会话失败 (MAC: %s): %v", mac, err) + return "", err + } + + return sessionId, nil +} + +// 获取会话并自动续期 +func GetAndRefreshSession(mac string, expiration time.Duration) (string, bool) { + ctx := context.Background() + key := getSessionKey(mac) + + // 使用 Lua 脚本保证原子性:获取值 + 刷新过期时间 + script := redis.NewScript(` + local key = KEYS[1] + local expire = tonumber(ARGV[1]) + + local value = redis.call("GET", key) + if not value then + return nil + end + + redis.call("EXPIRE", key, expire) + return value + `) + + result, err := script.Run(ctx, redisClient, []string{key}, expiration.Seconds()).Result() + if err != nil { + if err == redis.Nil { + return "", false + } + log.Printf("会话获取失败 (MAC: %s): %v", mac, err) + return "", false + } + + return result.(string), true +} diff --git a/pkg/setting/section.go b/pkg/setting/section.go index a3ff931..97f17b2 100644 --- a/pkg/setting/section.go +++ b/pkg/setting/section.go @@ -104,6 +104,14 @@ type RabbitMqSettings struct { RoutingKey string } +type RedisSettings struct { + Host string + Port string + Username string + Password string + Dbname int +} + func (s *Setting) ReadSection(k string, v interface{}) error { return s.vp.UnmarshalKey(k, v) } diff --git a/service/speechNlu/domain.go b/service/speechNlu/domain.go index 1361b33..80576b4 100644 --- a/service/speechNlu/domain.go +++ b/service/speechNlu/domain.go @@ -7,6 +7,7 @@ import ( "regexp" "speech-nlu-parse/global" "speech-nlu-parse/model" + "speech-nlu-parse/pkg/database" "speech-nlu-parse/pkg/logger" "speech-nlu-parse/service/connect" "strconv" @@ -56,7 +57,8 @@ func baseParse(params *model.SpeechDomainParams) (*model.ResponseBody, error) { // fmt.Println("保存:", params.SpeechWsResp.SessionId) // UpdateSession(params.Mac, params.SpeechWsResp.SessionId) //} - UpdateSession(params.Mac, params.SpeechWsResp.SessionId) + //UpdateSession(params.Mac, params.SpeechWsResp.SessionId) + database.UpdateSession(params.Mac, params.SpeechWsResp.SessionId) return &result, nil } @@ -442,7 +444,8 @@ func alarmDomain(params *model.SpeechDomainParams) []byte { if !params.SpeechWsResp.Dm.ShouldEndSession { fmt.Println("保存:", params.SpeechWsResp.SessionId) - UpdateSession(params.Mac, params.SpeechWsResp.SessionId) + //UpdateSession(params.Mac, params.SpeechWsResp.SessionId) + database.UpdateSession(params.Mac, params.SpeechWsResp.SessionId) return Marshal(params, &result) } diff --git a/service/speechNlu/redis.go b/service/speechNlu/redis.go deleted file mode 100644 index ffd6575..0000000 --- a/service/speechNlu/redis.go +++ /dev/null @@ -1,63 +0,0 @@ -package speechNlu - -//var redisClient *redis.Client -// -//// 初始化 Redis 连接 -//func InitRedis(addr, password string, db int) { -// redisClient = redis.NewClient(&redis.Options{ -// Addr: addr, -// Password: password, -// DB: db, -// }) -// -// if err := redisClient.Ping(context.Background()).Err(); err != nil { -// log.Fatalf("Redis连接失败: %v", err) -// } -//} -// -//// 更新会话(首次创建或续期) -//func UpdateSession(mac, sessionId string, expiration time.Duration) { -// ctx := context.Background() -// key := getSessionKey(mac) -// -// // 直接设置键值并指定过期时间 -// err := redisClient.Set(ctx, key, sessionId, expiration).Err() -// if err != nil { -// log.Printf("会话更新失败 (MAC: %s): %v", mac, err) -// } -//} -// -//// 获取会话并自动续期 -//func GetAndRefreshSession(mac string, expiration time.Duration) (string, bool) { -// ctx := context.Background() -// key := getSessionKey(mac) -// -// // 使用 Lua 脚本保证原子性:获取值 + 刷新过期时间 -// script := redis.NewScript(` -// local key = KEYS[1] -// local expire = tonumber(ARGV[1]) -// -// local value = redis.call("GET", key) -// if not value then -// return nil -// end -// -// redis.call("EXPIRE", key, expire) -// return value -// `) -// -// result, err := script.Run(ctx, redisClient, []string{key}, expiration.Seconds()).Result() -// if err != nil { -// if err == redis.Nil { -// return "", false -// } -// log.Printf("会话获取失败 (MAC: %s): %v", mac, err) -// return "", false -// } -// -// return result.(string), true -//} -// -//func getSessionKey(mac string) string { -// return fmt.Sprintf("session:%s", mac) -//} diff --git a/service/speechNlu/speech.go b/service/speechNlu/speech.go index 93494e6..9f446ff 100644 --- a/service/speechNlu/speech.go +++ b/service/speechNlu/speech.go @@ -4,10 +4,10 @@ import ( "encoding/json" "fmt" "github.com/gorilla/websocket" - "log" "speech-nlu-parse/dao" "speech-nlu-parse/global" "speech-nlu-parse/model" + "speech-nlu-parse/pkg/database" "speech-nlu-parse/pkg/errCode" "speech-nlu-parse/pkg/logger" "speech-nlu-parse/pkg/util" @@ -57,16 +57,19 @@ func SpeechNlu(reqStruct *model.SemanticReq) (string, *errCode.Error) { } else { var sessionId string // 自动清理过期Session的守护协程 - go StartSessionJanitor(1 * time.Minute) - - // 自动携带有效SessionID(自动刷新时间戳) - if sessionID, valid := GetAndRefreshSession(reqStruct.MacVoice, 30); valid { - sessionId = sessionID - log.Printf("检测到有效SessionID: %s", sessionID) - } else { - log.Println("Session已过期或无可用Session") - sessionId = "" - } + //go StartSessionJanitor(1 * time.Minute) + + sessionId, err = database.GetSession(reqStruct.MacVoice) + //log.Println("拿到的sessionId:", sessionId) + + //// 自动携带有效SessionID(自动刷新时间戳) + //if sessionID, valid := GetAndRefreshSession(reqStruct.MacVoice, 30); valid { + // sessionId = sessionID + // log.Printf("检测到有效SessionID: %s", sessionID) + //} else { + // log.Println("Session已过期或无可用Session") + // sessionId = "" + //} start := time.Now() data := SpeechNlpWsReq(reqStruct, sessionId) -- GitLab