Skip to content

Conversation

@duzhiruo
Copy link

尊敬的作者,您好:
最近在项目中使用到了您的kratos框架,我受益匪浅,感谢您能将如此优秀的作品开源分享。
在使用中,我发现有一个问题,希望能与您探讨。
您在中间件中使用了这样的设计:当客户端发起请求,从中间件开始,依次执行,后执行hander,再依次通过中间件返回。
我看到您在Docs说明了,可以自定义中间件,但当我加入缓存中间件时,发现这样一个问题:本代码似乎不支持缓存中间件命中缓存的情况。
下面是我自定义的缓存中间件相关代码,当命中缓存时,直接返回缓存结果,进入中间件返回链路,跳过了内层hander。
//Request Cache middleware
func RequestCacheCache() middleware.Middleware {
return func(handler middleware.Handler) middleware.Handler {
return func(ctx context.Context, req interface{}) (reply interface{}, err error) {
if info, ok := transport.FromClientContext(ctx); ok {
if trans, ok := info.(http.Transporter); ok {
cacheKey := generateCacheKey(trans.Request())
cache, _ := ctx.Value(server.ContextCacheKey).(*server.RequestCache)
if cache != nil {
if value, ok := cache.Get(cacheKey); ok {
return value, nil
}
reply, err = handler(ctx, req)
if err == nil {
cache.Set(cacheKey, reply)
}
return reply, err
}
}
}
return handler(ctx, req)

            }
    }

}

在 kratos 代码的/go-kratos/kratos/[email protected]/transport/http/client.go的invoke方法中:
执行逻辑是:先依次执行中间件,后执行内层h方法,在h闭包中给reply变量赋值并返回,再依次执行中间件。最终将结果返回_, err := h(ctx, args)。我想您是因为在h闭包中已经给reply赋值,所以这里并没有接收这个返回值。

而如果加入缓存中间件,命中缓存的话会直接跳过h,也就是说没有给reply赋值,也就不能实现缓存赋值了。是否这边可以在invoke方法中做一步改进呢?将reply的赋值操作分离出来,让它支持在命中缓存时,也能给reply赋值呢?
我查阅了 kratos 的文档以及在网上搜索了相关的解决方案,但仍然没有找到有效的解决办法。因此,我冒昧地给您写这封邮件,希望能得到您的帮助和指导。
我非常欣赏 kratos 框架的设计理念和强大的功能,它为我的项目带来了很大的便利。我相信,在您的专业知识和经验的帮助下,我一定能够顺利解决这个问题,继续推进我的项目。

再次感谢您的付出和支持。期待您的回复!

姓名:杜芝若
邮箱:[email protected] (非常期待得到您的回复)

@dosubot dosubot bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Aug 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant