From 3e5e0f8f1b99086bfd610be447644621c3f48385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Mon, 3 Jun 2024 18:42:46 +0800 Subject: [PATCH] =?UTF-8?q?rpc=E7=BC=93=E5=AD=98=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E7=9A=84=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cache/ICache.go | 54 ++++++++++++++++++++++++++++++++++++++ client.go | 65 ++++++++++++++++++++++++++++++++++++++++++++-- define/response.go | 7 ++++- 3 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 cache/ICache.go diff --git a/cache/ICache.go b/cache/ICache.go new file mode 100644 index 0000000..3d9c9be --- /dev/null +++ b/cache/ICache.go @@ -0,0 +1,54 @@ +// Package cache ... +// +// Description : cache ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2024-06-03 15:49 +package cache + +import "git.zhangdeman.cn/gateway/httpclient/define" + +// ICache 缓存定义 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 15:49 2024/6/3 +type ICache interface { + // Enable 是否启用缓存(总开关) + // + // Author : go_developer@163.com<白茶清欢> + // + // Date : 15:50 2024/6/3 + Enable() bool + // CacheTime 缓存时长, 单位 : s , 默认 1800, 最小值 90, 设置失效时间, 会上下波动60s, 避免缓存集中失效 + // + // Author : go_developer@163.com<白茶清欢> + // + // Date : 15:50 2024/6/3 + CacheTime() int64 + // IsAllow 针对当前请求数据和状态, 是否允许缓存 + // + // Author : go_developer@163.com<白茶清欢> + // + // Date : 15:52 2024/6/3 + IsAllow(reqCfg *define.Request, response *define.Response) bool + // GetKey 获取缓存key + // + // Author : go_developer@163.com<白茶清欢> + // + // Date : 15:51 2024/6/3 + GetKey(reqCfg *define.Request) string + // GetValue 获取缓存值 + // + // Author : zhangdeman001@ke.com<张德满> + // + // Date : 16:01 2024/6/3 + GetValue(cacheKey string) string + // SetValue 设置缓存 + // + // Author : go_developer@163.com<白茶清欢> + // + // Date : 16:46 2024/6/3 + SetValue(cacheKey string, cacheValue string) error +} diff --git a/client.go b/client.go index 9115d85..67335e9 100644 --- a/client.go +++ b/client.go @@ -8,9 +8,12 @@ package httpclient import ( + "git.zhangdeman.cn/gateway/httpclient/cache" "git.zhangdeman.cn/gateway/httpclient/define" "git.zhangdeman.cn/gateway/httpclient/validate" + "git.zhangdeman.cn/zhangdeman/serialize" "github.com/go-resty/resty/v2" + "strings" "time" ) @@ -19,7 +22,7 @@ import ( // Author : go_developer@163.com<白茶清欢> // // Date : 15:27 2024/5/31 -func NewHttpClient(reqConfig *define.Request) (*HttpClient, error) { +func NewHttpClient(reqConfig *define.Request, cacheInstance cache.ICache) (*HttpClient, error) { // 验证配置正确性以及初始化默认值 if err := validate.RequestConfig(reqConfig); nil != err { return nil, err @@ -33,6 +36,7 @@ func NewHttpClient(reqConfig *define.Request) (*HttpClient, error) { http5xxHandler: make([]define.Http5xxHandler, 0), httpBusinessErrorHandler: make([]define.HttpBusinessErrorHandler, 0), requestFinishHandler: make([]define.RequestFinishHandler, 0), + cacheInstance: cacheInstance, } return hc, nil } @@ -51,6 +55,7 @@ type HttpClient struct { httpBusinessErrorHandler []define.HttpBusinessErrorHandler requestSendErrorHandler []define.RequestSendErrorHandler requestFinishHandler []define.RequestFinishHandler + cacheInstance cache.ICache } // OnResponse4xx 4xx处理逻辑 @@ -135,6 +140,14 @@ func (hc *HttpClient) GetRestyClient() *resty.Client { // // Date : 15:52 2024/5/31 func (hc *HttpClient) Request() *define.Response { + var ( + cacheResult *define.Response + ) + + if cacheResult = hc.getCacheResult(); nil != cacheResult { + return cacheResult + } + hc.Client.OnBeforeRequest(hc.getRequestValidateMiddleware()) // 请求参数验证中间件必注册 hc.Client.OnAfterResponse(hc.getResponseValidateMiddleware()) // 响应验证中间件必注册 var ( @@ -169,7 +182,7 @@ func (hc *HttpClient) newResponse(seq int, requestCount int) *define.Response { ResponseDataRule: nil, Seq: seq, RequestStartTime: 0, - FinishRequestTime: 0, + RequestFinishTime: 0, UsedTime: 0, RestyResponse: nil, IsSuccess: false, @@ -177,3 +190,51 @@ func (hc *HttpClient) newResponse(seq int, requestCount int) *define.Response { FailInfo: nil, } } + +// getCacheResult 获取缓存结果 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 16:04 2024/6/3 +func (hc *HttpClient) getCacheResult() *define.Response { + if nil == hc.cacheInstance || !hc.cacheInstance.Enable() { + return nil + } + startTime := time.Now().UnixMilli() + cacheKey := hc.cacheInstance.GetKey(hc.reqConfig) + cacheValue := strings.TrimSpace(hc.cacheInstance.GetValue(cacheKey)) + if len(cacheValue) == 0 { + return nil + } + response := hc.newResponse(-1, -1) + if err := serialize.JSON.UnmarshalWithNumber([]byte(cacheValue), response); nil != err { + return nil + } + response.IsCache = true // 设置缓存标记 + response.RequestStartTime = startTime // 开始时间 + response.RequestFinishTime = time.Now().UnixMilli() // 结束时间 + response.UsedTime = response.RequestFinishTime - response.RequestStartTime // 耗时 + response.CacheKey = cacheKey // 缓存key + response.CacheValue = cacheValue // 缓存值 + return response +} + +// setCacheResult ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 16:24 2024/6/3 +func (hc *HttpClient) setCacheResult(response *define.Response) (bool, error) { + if nil == response || nil == hc.cacheInstance { + return false, nil + } + // 全局未开启或者当前请求不支持缓存 + if !hc.cacheInstance.Enable() || !hc.cacheInstance.IsAllow(hc.reqConfig, response) { + return false, nil + } + cacheKey := hc.cacheInstance.GetKey(hc.reqConfig) + if err := hc.cacheInstance.SetValue(cacheKey, serialize.JSON.MarshalForString(response)); nil != err { + return false, err + } + return true, nil +} diff --git a/define/response.go b/define/response.go index f8ca2da..5be913b 100644 --- a/define/response.go +++ b/define/response.go @@ -28,12 +28,17 @@ type Response struct { ResponseDataRule map[string]any `json:"response_data_rule"` // 返回数据的验证规则 Seq int `json:"seq"` // 第几次请求 RequestStartTime int64 `json:"request_start_time"` // 请求开始时间 : ms - FinishRequestTime int64 `json:"finish_request_time"` // 请求完成时间 : ms + RequestFinishTime int64 `json:"request_finish_time"` // 请求完成时间 : ms UsedTime int64 `json:"used_time"` // 请求耗时 : ms RestyResponse *resty.Response `json:"-"` // 请求返回 IsSuccess bool `json:"is_success"` // 是否请求成功 RequestCount int `json:"request_count"` // 请求次数 FailInfo *ResponseFileInfo `json:"fail_info"` // 请求失败信息记录 + IsCache bool `json:"-"` // 是否命中缓存 + CacheKey string `json:"-"` // 缓存key + CacheValue string `json:"-"` // 缓存值 + CacheEnable bool `json:"cache_enable"` // 是否允许缓存 + CacheError error `json:"-"` // 缓存是否异常 } // ResponseFileInfo 失败信息