带你读《云原生应用开发:Operator原理与实践》——2.2.7 Transport 说明

简介: 带你读《云原生应用开发:Operator原理与实践》——2.2.7 Transport 说明

2.2.7 Transport 说明


本节简要介绍 Client-go 源码中 Transport 包的实现和底层原理。


1. Transport 功能说明

Transport 提 供 认 证 授 权 安 全 的 传 输 控 制 协 议(TCP,Transmission Control Protocol)连接,基于 SPDY 协议支持 HTTP 流(Stream)传输机制。Transport 包是通过自定义 Transport 对 http.Client 的定制化封装实现的,在 Client-go 源码中作为工具包为 RESTClient 封装 HTTP 客户端请求。在实际开发过程中,一般只需要调用 Client-go中提供的 RESTClient、DiscoveryClient、ClientSet、DynamicClient 即可。


2. Transport 的内部实现

Transport 包主要是对 http.RoundTripper 的封装实现,为了更好地理解本节内容,首先介绍 http.RoundTripper 的概念和实现,然后介绍 Transport 是怎样封装 http.RoundTripper的。最后简要介绍 Client-go 包中底层的 RESTClient 是如何使用 Transport 的。

(1) http.RoundTripper

http.RoundTripper 能够执行单个 HTTP 事务,获取给定请求的响应。实现 http.Round Tripper 接口的代码通常需要在多个 Goroutine 中并发执行,因此,必须确保实现代码的线程安全性。http.RoundTripper 是在 Go 语言 HTTP 包中定义的接口,接口定义见代码清单 2-49。

代码清单 2-49

type RoundTripper interface { 
 RoundTrip(*Request) (*Response, error)
}

从上述代码中可以看出,http.RoundTripper 接口很简单,只定义了一个名为 RoundTrip 的方法。RoundTrip() 方法用于执行一个独立的 HTTP 事务,接收传入的 *Request 请求值作为参数并返回对应的 *Response 响应值,以及一个 error 值。任何实现了 RoundTrip() 方法的类型都实现了 http.RoundTripper 接口。代码清单 2-50 简单展示了 http.RoundTripper 接口的实现。

代码清单 2-50

type testTransport struct {
 agent string
 originalTransport http.RoundTripper
}
func (c *testTransport) RoundTrip(r *http.Request) (*http.Response, error) {
 if len(r.Header.Get("User-Agent")) != 0 {
 return c.originalTransport.RoundTrip(r)
 }
 r = utilnet.CloneRequest(r)
 r.Header.Set("User-Agent", c.agent)
 resp, err := c.originalTransport.RoundTrip(r)
 if err != nil {
 return nil, err
 }
 return resp, nil
}

上述代码定义了一个 testTransport 结构体类型,通过实现该类型的 RoundTrip 方法实现了该类型的 http.RoundTripper 接口。该接口的功能是在 HTTP 的请求头中添加 User-Agent 参数。通过以上 http.RoundTripper 接口的简单实现,我们了解了 http.RoundTripper 接口是如何封装 HTTP 请求的。Transport 包中以同样的方式实现了多种封装类型。下面具体介绍 Transport 包中 http.RoundTripper 的封装。

(2) Transport 包中对 http.RoundTripper 的封装

Transport 包中定义了 New 函数,该函数通过传入的 Config 参数创建 http.RoundTripper,具体见代码清单 2-51。

代码清单 2-51

func New(config *Config) (http.RoundTripper, error) {
 // 设置 Transport 的安全级别
 if config.Transport != nil && (config.HasCA() || config.HasCertAuth() || 
config.HasCertCallback() || config.TLS.Insecure) {
 return nil, fmt.Errorf("using a custom transport with TLS certificate 
options or the insecure flag is not allowed")
 }
 var (
 rt http.RoundTripper
 err error
 )
 if config.Transport != nil {
 rt = config.Transport
 } else {
 rt, err = tlsCache.get(config)
 if err != nil {
 return nil, err
 }
 }
 return HTTPWrappersForConfig(config, rt)
}

在 New 函数中,首先通过 config 对象的方法获取认证信息,如果认证信息是非安全设置的,则返回 nil;如果配置中满足安全设置,则 New 函数会读取配置中的 Transport 信息;如果 Transport 为空,New 函数就从缓存中读取缓存的 Transport,如果缓存中没有Transport,那么需要初始化一个默认的 Transport。最后调用 HTTPWrappersForConfig函数,该函数将 Config 作为参数对 Transport 进行进一步的封装。HTTPWrappersForConfig 函数见代码清单 2-52。

代码清单 2-52

func HTTPWrappersForConfig(config *Config, rt http.RoundTripper) (http.RoundTripper, 
error) {
 if config.WrapTransport != nil {
 rt = config.WrapTransport(rt)
 }
 rt = DebugWrappers(rt)
 // Set authentication wrappers
 switch {
 case config.HasBasicAuth() && config.HasTokenAuth():
 return nil, fmt.Errorf("username/password or bearer token may be set, but not 
both")
 case config.HasTokenAuth():
 var err error
 rt, err = NewBearerAuthWithRefreshRoundTripper(config.BearerToken, config.
BearerTokenFile, rt)
 if err != nil {
 return nil, err
 }
 case config.HasBasicAuth():
 rt = NewBasicAuthRoundTripper(config.Username, config.Password, rt)
 }
 if len(config.UserAgent) > 0 {
 rt = NewUserAgentRoundTripper(config.UserAgent, rt)
 }
 if len(config.Impersonate.UserName) > 0 ||
 len(config.Impersonate.Groups) > 0 ||
 len(config.Impersonate.Extra) > 0 {
 rt = NewImpersonatingRoundTripper(config.Impersonate, rt)
 }
 return rt, nil
}

HTTPWrappersForConfig 函 数 可 以 根 据 不 同 配 置 的 认 证 信 息 创 建 不 同 的 http.Round‐ Tripper。由以上代码可知该函数共创建了 4 种不同类型的 http.RoundTripper。

① NewBearerAuthWithRefreshRoundTripper 创建了 BearerAuthWithRefreshRoundTripper 类型对象,实现了 http.RoundTripper 接口,并将提供的 Bearer 令牌添加到请求中,如果 tokenFile 是非空的,则定期读取 tokenFile,最后一次成功读取的内容作为 Bearer 令牌;如果 tokenFile 是非空的,而 Bearer 是空的,tokenFile会被立即读取,以填充初始的 Bearer 令牌。

② NewBasicAuthRoundTripper 创建了 basicAuthRoundTripper 类型对象,它将基本 auth 授权应用到请求中,通过用户名和密码授权实现 http.RoundTripper 接口。

③ NewUserAgentRoundTripper 创建了 userAgentRoundTripper 类型对象,它向请求添加 User-Agent 请求头,实现了 http.RoundTripper 接口。

④ NewImpersonatingRoundTripper 创建了 ImpersonatingRoundTripper 类型对象,向请求添加一个 Act-As 请求头,实现了 http.RoundTripper 接口。

以上 4 种不同类型的 http.RoundTripper 实现方式与 2.2.6 节的案例实现是同一种方式,这里不再赘述。除了以上 4 种不同类型的 http.RoundTripper 对 http.RoundTripper 接口的实现,Transport 中还包括 authProxyRoundTripper、debuggingRoundTripper 等其他类型,具体可在 /client-go/transport/round_trippers.go 文件中查看。

(3) Transport 的使用案例

Client-go 源码 Rest 包中通过 RESTClientFor 返回一个 RESTClient 对象,RESTClient对 Kubernetes APIServer 的 RESTful API 的访问进行了封装抽象。RESTClientFor 的实现见代码清单 2-53。

代码清单 2-53

func RESTClientFor(config *Config) (*RESTClient, error) {
 ...
 transport, err := TransportFor(config)
 if err != nil {
 return nil, err
 }
 var httpClient *http.Client
 if transport != http.DefaultTransport {
 httpClient = &http.Client{Transport: transport}
 if config.Timeout > 0 {
 httpClient.Timeout = config.Timeout
 }
 }
 ...
 restClient, err := NewRESTClient(baseURL, versionedAPIPath, clientContent, 
rateLimiter, httpClient)
 if err == nil && config.WarningHandler != nil {
 restClient.warningHandler = config.WarningHandler
 }
 return restClient, err
}
func TransportFor(config *Config) (http.RoundTripper, error) {
 cfg, err := config.TransportConfig()
 if err != nil {
 return nil, err
 }
 return transport.New(cfg)
}

以上代码是通过函数 RESTClientFor 传入客户端配置参数 Config 来创建 RESTClient的,函数通过调用 TransportFor 函数创建了一个 Transport,在上述代码的最后一行,可 以 看 出 该 函 数 是 通 过 调 用 Transport 包 中 的 New 函 数 创 建 了 http.RoundTripper。

TransportFor 函数通过将客户端 Config 配置转化为 Transport 包中的 Config 类型并调用New 函数创建 http.Transport。通过 New 函数实现了底层 HTTP 不同请求的封装,实现了 HTTP 客户端的安全连接。

相关文章
|
13天前
|
Kubernetes 监控 Cloud Native
云原生时代下的应用开发与部署实践
【10月更文挑战第4天】在云原生的浪潮中,开发者和运维人员面临着新的挑战和机遇。本文将通过实际案例,展示如何在云平台上高效地开发、部署和管理应用,同时确保系统的可扩展性和高可用性。我们将深入探讨容器化技术、微服务架构以及持续集成/持续部署(CI/CD)流程的实施策略,旨在为读者提供一套完整的云原生解决方案框架。
|
1月前
|
Kubernetes Cloud Native 持续交付
云原生技术在现代应用开发中的角色与实践
【9月更文挑战第9天】 随着云计算技术的飞速发展,云原生(Cloud Native)已经成为推动企业数字化转型的核心力量。本文将深入探讨云原生的基本概念、关键技术及其在实际开发中的应用案例,旨在为读者提供一条清晰的云原生技术学习路径和应用指南。通过实例分析,我们将揭示云原生如何优化资源管理、提升应用性能及加快部署速度,进而帮助企业构建更加灵活、可靠和高效的软件系统。
|
2天前
|
Kubernetes Cloud Native 持续交付
云原生技术:重塑现代应用开发与部署模式####
本文深入探讨了云原生技术的核心概念、发展历程及其在现代软件开发和部署中的关键作用。通过分析云原生架构的特点,如容器化、微服务、持续集成与持续部署(CI/CD),以及它如何促进应用的可伸缩性、灵活性和效率,本文旨在为读者提供一个关于云原生技术全面而深入的理解。此外,还将探讨实施云原生策略时面临的挑战及应对策略,帮助组织更好地把握数字化转型的机遇。 ####
|
2天前
|
人工智能 Serverless API
云原生应用开发平台CAP:一站式应用开发及生命周期管理解决方案
阿里云的云应用开发平台CAP(Cloud Application Platform)是一款一站式应用开发及应用生命周期管理平台。它提供丰富的Serverless与AI应用模板、高效的开发者工具链及企业级应用管理功能,帮助开发者快速构建、部署和管理云上应用,大幅提升研发、部署和运维效能。
15 1
|
10天前
|
Kubernetes Cloud Native 持续交付
云原生技术在现代应用开发中的实践与展望
【10月更文挑战第7天】随着技术的不断演进,云计算已从简单的资源租用模式转变为支持复杂、高效、灵活的云原生应用架构。本文将深入探讨云原生技术的核心概念及其在现代应用开发中的应用,通过分析Kubernetes容器编排和微服务架构的实践案例,揭示云原生技术如何推动软件开发的现代化进程。文章旨在为开发者和架构师提供一套实用的云原生应用开发指南,同时展望未来云原生技术的发展方向。
20 8
|
25天前
|
Cloud Native 测试技术 云计算
云原生技术在现代应用开发中的角色与实践
【9月更文挑战第31天】本文深入探讨了云原生技术如何革新现代应用开发流程,通过实际案例分析,揭示了其对提高开发效率、确保系统可扩展性和可靠性的显著影响。文章不仅介绍了云原生的核心概念,还提供了实施策略和最佳实践,旨在为开发者提供一条清晰的云原生转型之路。
|
1月前
|
Kubernetes Cloud Native 持续交付
云原生技术在现代应用开发中的实践与思考
【9月更文挑战第23天】本文将深入探讨云原生技术如何革新现代应用的开发流程。通过分析云原生的核心概念、优势以及实际应用案例,我们旨在揭示这一新兴技术范式如何助力开发者和企业更高效、灵活地构建和部署应用程序。文章还将提供具体代码示例,展示云原生技术在实际项目中的应用,帮助读者更好地理解和掌握该技术。
|
1月前
|
Cloud Native 持续交付 开发者
云原生技术在现代应用开发中的应用与实践
【9月更文挑战第22天】本文将深入探讨云原生技术如何革新现代应用开发,通过实际案例分析其对提高开发效率、促进持续集成与交付的显著影响。我们将从云原生的基本概念出发,逐步展开到容器化、微服务架构、自动化管理的实践操作,以及这些技术如何协同工作以支持复杂应用的快速迭代和扩展。文章旨在为开发者提供一套云原生技术的实践框架,帮助他们构建更加灵活、可维护的应用系统。
|
1月前
|
Cloud Native 持续交付 云计算
云原生技术在现代应用开发中的应用与实践
【9月更文挑战第12天】随着云计算技术的飞速发展,云原生已成为推动企业数字化转型的关键技术之一。本文将深入探讨云原生的基本概念、核心价值及其在现代应用开发中的实际应用案例,旨在为读者提供一套清晰的云原生应用开发指南。通过分析容器化、微服务架构、持续部署等核心技术的实践过程,我们将揭示云原生如何助力开发者高效构建、部署和管理可扩展的应用。你将看到代码示例,这些示例均选自真实世界的开发场景,帮助你理解云原生技术的强大功能和灵活性。
|
1月前
|
运维 Cloud Native 持续交付
云原生技术:探索现代应用开发的新纪元
本文深入探讨了云原生技术的崛起,以及它如何彻底改变现代应用开发和部署的方式。我们将从云原生的基本概念入手,逐步解析其核心技术如容器化、微服务架构及自动化运维,并展示这些技术如何帮助开发者和企业实现更高效、更灵活的应用管理。通过实际案例分析,我们将揭示云原生技术在提升开发效率、优化资源利用和增强系统可扩展性方面的巨大潜力。