K8s源码分析(20)-client go组件之request和result
2023-06-13 09:14:14 时间
上一篇文章里,我们主要介绍了 kubernetes 世界中 client go 这个基础组件,它的主要职责是负责与 API server 进行通讯交互。其中负责资源调度的 kube-scheduler 组件,负责资源管理的 controller manager 组件,以及负责 pod 生命周期的 kublet 组件,负责网络管理的 kube-proxy 组件都会依赖于这个组件。而该组件在通讯的时候又依赖于 request 对象,并且得到相应的 result 对象,在本篇文章里我们主要来介绍 request 和 result 对象。
Request 结构体
该结构体主要封装了上一篇文章中介绍的 RESTClient 对象,用以完成和 API server 之间的通讯,其图解和相关源码如下:
type Request struct {
c *RESTClient
warningHandler WarningHandler
rateLimiter flowcontrol.RateLimiter
backoff BackoffManager
timeout time.Duration
maxRetries int
verb string
pathPrefix string
subpath string
params url.Values
headers http.Header
namespace string
namespaceSet bool
resource string
resourceName string
subresource string
err error
body io.Reader
}
func (r *Request) Do(ctx context.Context) Result {
var result Result
err := r.request(ctx, func(req *http.Request, resp *http.Response) {
result = r.transformResponse(resp, req)
})
if err != nil {
return Result{err: err}
}
return result
}
func (r *Request) transformResponse(resp *http.Response, req *http.Request) Result {
............
var decoder runtime.Decoder
contentType := resp.Header.Get("Content-Type")
if len(contentType) == 0 {
contentType = r.c.content.ContentType
}
............
decoder, err = r.c.content.Negotiator.Decoder(mediaType, params)
............
return Result{
body: body,
contentType: contentType,
statusCode: resp.StatusCode,
decoder: decoder,
warnings: handleWarnings(resp.Header, r.warningHandler),
}
}
- 在该结构体的源码定义中, 封装了上一篇文章中介绍的 RESTClient 对象。同时也封装对应的 http 请求方法 verb,路径的前缀 pathPrefix ,以及请求参数和请求头等有关必要信息。
- 在该结构体中还封装了资源的信息,例如是本次操作的资源是否为基于 namespace 的资源,具体资源是属于哪个命名空间的,资源的种类,资源的名字,还有子资源的种类等等。
- 该结构体中封装了 Do() 方法用以发送请求和处理响应。
- 封装了 transformResponse() 方法用完成对 API 响应的封装操作,其核心是调用上一篇文章中介绍的 ClientNegotiator 定义的 Decoder 方法来得到相应的 decoder,然后封装到一个 Result 对象中。
Result 结构体
该结构体主要封装了请求对象和 API server 交互的结果,并提供反序列化得到相应资源对象的功能,其图解和相关源码如下:
type Result struct {
body []byte
warnings []net.WarningHeader
contentType string
err error
statusCode int
decoder runtime.Decoder
}
func (r Result) Into(obj runtime.Object) error {
if r.err != nil {
// Check whether the result has a Status object in the body and prefer that.
return r.Error()
}
if r.decoder == nil {
return fmt.Errorf("serializer for %s doesn't exist", r.contentType)
}
if len(r.body) == 0 {
return fmt.Errorf("0-length response with status code: %d and content type: %s",
r.statusCode, r.contentType)
}
out, _, err := r.decoder.Decode(r.body, nil, obj)
if err != nil || out == obj {
return err
}
// if a different object is returned, see if it is Status and avoid double decoding
// the object.
switch t := out.(type) {
case *metav1.Status:
// any status besides StatusSuccess is considered an error.
if t.Status != metav1.StatusSuccess {
return errors.FromObject(t)
}
}
return nil
}
- 在该结构体的源码定义中, 封装了响应返回的二进制结果 body,同时也封装了对应的 decoder 对象用来反序列化。
- 该接结构体中封装了 Into() 方法用完成对结果的反序列化操作,其核心就是调用内部的 decoder 对象来把结果转化为对应的资源对象。
目前先我们写到这里,在下一篇文章中我们继续来介绍对于不同 group/version 的资源是如何通过发送请求来操作的。
相关文章
- K8s小白?应用部署太难?看这篇就够了!
- K8s client-go watch pod
- 公网环境搭建 k8s 集群
- 图解K8s源码 - kubelet 下的 QoS 控制机制及 k8s Cgroups v2 简介
- k8s之StatefulSet
- k8s之DaemonSet
- k8s系列-helm
- 「Go工具箱」一个对语义化版本进行解析、比较的库:go-version
- k8s上部署JupyterHub实现多用户空间(第一篇)
- Go 模块 verifying xxx/go.mod: checksum mismatch 问题处理
- Go-包管理-go get(二)
- go pprof命令(Go语言性能分析命令)完全攻略
- 使用Go语言来操作Oracle数据库(go语言oracle)
- 程序Linux上运行Go语言程序的指南(linux运行go)
- Go语言环境配置:在 Linux 下实现(go环境搭建linux)
- 如何在Linux上安装Go语言?——简单易懂的指南(linux安装go语言)
- MySQL中使用Go语言的好处(mysql中go什么)
- Go语言链接Oracle数据库的实践记录(go 链接oracle)
- 新技术Go语言解析Oracle数据库日志(go解析oracle日志)
- 数据库Go语言实现监控Oracle数据库(go监听oracle)
- 给Oracle数据库添加专业技能,Go大发展(go_db_oracle)
- Redis集群搭建Go的艰难之路(redis集群搭建go)
- Go语句让Oracle数据库管理更方便(oracle go语句)