【k8s】【DiscoveryClient】【缓存】

DiscoveryClient 缓存问题

缓存目录: 默认 /root/.kube/cache

k8s 使用DiscoveryClient 会对api-gvk信息进行缓存 因为这些信息不太需要变动
首先维护的缓存包括两份数据 http和discovery cache。
http cache 比 discovery cache大一些,多出来的部分主要是由于http cache保存的是responce头部和body 而 discovery cache保存body json,http cache会额外保存/openapi/v2的响应 并使用其作为cache。
.diskv-temp 是为了保证原子性写入的文件 每次缓存会先写入临时文件 再将临时文件命名为缓存文件。
缓存的key为:

func cacheKey(req *http.Request) string {
	if req.Method == http.MethodGet {
		return req.URL.String()
	} else {
		return req.Method + " " + req.URL.String()
	}
}

value为对应的 resp
当使用此cacheDiscoveryClient 时,即使拿到http响应数据时 对上层是无感知的 但可以通过观察返回响应中X-From-Cache:1的头部有无来观察此响应是否是cache返回
cache 使用包名称"github.com/gregjones/httpcache"
使用方法

	d := diskv.New(diskv.Options{
		PathPerm: os.FileMode(0750),
		FilePerm: os.FileMode(0660),
		BasePath: cacheDir,
		TempDir:  filepath.Join(cacheDir, ".diskv-temp"),
	})
	t := httpcache.NewTransport(diskcache.NewWithDiskv(d))

当上层获取gvk时 由于gvk不经常变动 采取CachediscoveryClient更加合理 此客户端维护本身的discovery缓存 实际是对resp的硬编码数据 维护方式依据gvk路径对json文件进行缓存
唯一的依据是文件时间 默认超时时间6h 当判断时间超时时 对此req重新发请求 并缓存编码之后结果

func NewCachedDiscoveryClientForConfig(config *restclient.Config, discoveryCacheDir, httpCacheDir string, ttl time.Duration) (*CachedDiscoveryClient, error) {
	if len(httpCacheDir) > 0 {
		// update the given restconfig with a custom roundtripper that
		// understands how to handle cache responses.
		config = restclient.CopyConfig(config)
		config.Wrap(func(rt http.RoundTripper) http.RoundTripper {
			return newCacheRoundTripper(httpCacheDir, rt)
		})
	}
	discoveryClient, err := discovery.NewDiscoveryClientForConfig(config)
	if err != nil {
		return nil, err
	}

	return newCachedDiscoveryClient(discoveryClient, discoveryCacheDir, ttl), nil
}

注意如果httpCacheDir 为空 由于RoundTripper未被自定义设置 将不会对缓存文件进行读取(个别)并返回请求 而是直接使用真实的请求 。
在请求/openapi/v2时 当http cache中不存在 会使用真实请求 否则 使用http cache中的值(在http cache中能够使用缓存cache的主要是以下情况

go/pkg/mod/github.com/gregjones/httpcache@v0.0.0-20180305231024-9cad4c3443a7/httpcache.go
1,服务器支持 服务器对此请求返回对应的etag 等值 并允许缓存此响应(get,head请求 非range)
2,当包括重新修剪if-none-match,last-modified头部,将其发送给apiserver,当apiserver认为当前请求的if-none-match,last-modified符合要求 会返回304响应和
空的结构体  判断逻辑如下
		resp, err = transport.RoundTrip(req)
		if err == nil && req.Method == "GET" && resp.StatusCode == http.StatusNotModified {
			// Replace the 304 response with the one from cache, but update with some new headers 这里可以重用cache
			endToEndHeaders := getEndToEndHeaders(resp.Header)
			for _, header := range endToEndHeaders {
				cachedResp.Header[header] = resp.Header[header]
			}
			resp = cachedResp
		} else if (err != nil || (cachedResp != nil && resp.StatusCode >= 500)) &&
			req.Method == "GET" && canStaleOnError(cachedResp.Header, req.Header) {
			// In case of transport failure and stale-if-error activated, returns cached content  这种情况k8s不会发生 因为resp不会额外设置头部 
			// when available
			return cachedResp, nil
		} else {
			if err != nil || resp.StatusCode != http.StatusOK {
				t.Cache.Delete(cacheKey)
			}
			if err != nil {
				return nil, err
			}
		}

主要由于此部分不经常变动 并且内容较多 因此直接通过客户端缓存获取。
其他部分请求 实际均不会从http cache中拿取数据 而是从discovery cache中拿取明文数据 直到过期后 从 apiserver重新拿取数据 并写入discovery cache 缓存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值