spring-cloud-kubernetes 背后的三个关键知识点
欢迎访问我的 GitHub
这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
本篇概览
在前文《你好spring-cloud-kubernetes》一文中,对 spring-cloud-kubernetes 这个 SpringCloud 官方 kubernetes 服务框架有了基本了解,今天来小结此框架涉及的关键技术,为后面的深入学习做准备;
概览
总结下来有三个关键知识点需要深入理解:
DiscoveryClient 是个接口,对应的实现类是哪个?
discoveryClient.getServices()方法取得了 kubernetes 的 service 信息,这背后的机制是什么?java 应用是怎样取得所在 kubernetes 的服务信息的?
kubernetes 的 service 信息存在哪里?如何将这些信息给出去?
接下来我们逐一分析每个知识点;
DiscoveryClient 接口的实现类实例从何而来
先来回顾一下上一章的 DiscoveryController.java 的内容:
上述代码中,我们并没有写创建 DiscoveryClient 实例的代码,discoveryClient 从何而来?
这一切,要从 DiscoveryController.java 所在项目的 pom.xml 说起;
在 pom.xml 中,有对 spring-cloud-kubernetes 框架的依赖配置:
打开 spring-cloud-kubernetes-discovery 的源码,地址是:https://github.com/spring-cloud/spring-cloud-kubernetes/tree/master/spring-cloud-kubernetes-discovery ,在这个工程中发现了文件 spring.factories:
spring 容器启动时,会寻找 classpath 下所有 spring.factories 文件(包括 jar 文件中的),spring.factories 中配置的所有类都会实例化,我们在开发 springboot 时常用到的 XXX-starter.jar 就用到了这个技术,效果是一旦依赖了某个 starter.jar 很多功能就在 spring 初始化时候自动执行了(例如 mysql 的 starter,启动时会连接数据库),关于此技术的详情,请参考以下三篇文章:《自定义 spring boot starter 三部曲之一:准备工作》、《自定义 spring boot starter 三部曲之二:实战开发》、《自定义 spring boot starter 三部曲之三:源码分析 spring.factories 加载过程》
spring.factories 文件中有两个类:KubernetesDiscoveryClientAutoConfiguration 和 KubernetesDiscoveryClientConfigClientBootstrapConfiguration 都会被实例化;
先看 KubernetesDiscoveryClientConfigClientBootstrapConfiguration,很简单的源码,KubernetesAutoConfiguration 和 KubernetesDiscoveryClientAutoConfiguration 这两个类会被实例化:
在 KubernetesAutoConfiguration 的源码中,会实例化一个重要的类:DefaultKubernetesClient,如下:
再看 KubernetesDiscoveryClientAutoConfiguration 源码,注意 kubernetesDiscoveryClient 方法,这里面实例化了 DiscoveryController 所需的 DiscoveryClient 接口实现,还要重点关注的地方是 KubernetesClient 参数的值,是上面提到的 DefaultKubernetesClient 对象:
至此,第一个问题算是弄清楚了:我们编写的 DiscoveryController 类所需的 DiscoveryClient 接口实现类是 KubernetesDiscoveryClient,用到的是 spring 规范中的 spring.factories
另外有一点很重要,下面要用到的:KubernetesDiscoveryClient 有个成员变量是 KubernetesClient,该变量的值是 DefaultKubernetesClient 实例;
接下来看第二个问题;
java 应用怎么能取得所在 kubernetes 的服务信息
看看 DiscoveryController 是如何获取所在 kubernetes 的服务信息的:
如上所示,discoveryClient.getServices()方法返回了所有 kubernetes 的服务信息;
2. discoveryClient 对应的类是 spring-cloud-kubernetes 项目的 KubernetesDiscoveryClient.java,看方法:
这段代码的关键在于 this.kubernetesClientServicesFunction.apply(this.client).list(),先看 KubernetesClientServicesFunction 实例的初始化过程,在 KubernetesDiscoveryClientAutoConfiguration 类中:
KubernetesClientServicesFunction 是个 lambda 表达式,用于 KubernetesClient 的时候,返回 KubernetesClient.services()的结果,如果指定了标签过滤,就用指定的标签来做过滤(也就是 kubernetes 中的标签选择器的效果)
因此,数据来源其实就是上面的 this.client,调用其 services 方法的返回结果;
KubernetesDiscoveryClient.getServices 方法中的 this.client 是什么呢?分析前面的问题时已经提到过了,就是 DefaultKubernetesClient 类的实例,所以,此时要去看 DefaultKubernetesClient.services 方法,发现 client 是 ServiceOperationsImpl 实例:
接着看 ServiceOperationsImpl.java,我们关心的是它的 list 方法,此方法在父类 BaseOperation 中找到:
展开上面代码的 handleResponse 方法,可见里面是一次 http 请求,至于请求的地址,可以展开 getNamespacedUrl()方法,里面调用的 getRootUrl 方法如下:
可见最终的地址应该是:xxxxxx/api/v1 或者 xxxxxx/apis/xx/v1 这样的字符串。
这样的字符串意味着什么呢?这是访问 kubernetes 的 API Server 时用到的 URL 标准格式,有关 API Server 服务的详情请参考官方文档,地址是:https://kubernetes.io/docs/reference/using-api/api-concepts/
如下图,用 OperationSupport 类的源码和官方文档的 URL 截图做个对比,大家就一目了然了:
还剩个小问题,上图中,OperationSupport 类的成员变量 resourceT 是什么值?官方文档示例中是"pods",在获取 service 的时候又该是多少呢?顺着源码一路找下去,找到了类的构造方法,如下所示,第五个参数就是 resourceT,这里直接被写死为"services":
至此,第二个问题“controller 中用到的 kubernetes 服务数据从何而来"已经清楚了:最终是调用 okhttp 的 newCall 方法向 kubernetes 的 API Server 发起 http 请求,获取 service 资源的数据列表;
接下来,该最后一个问题了;
API Server 收到请求后做了什么?
关于 API Server 如何响应各类 http 请求,本文只做一些简单的说明,详细信息还请参考官方文档,地址是:https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/
如下图所示,在 kubernetes 环境中,pod、service 这些资源的数据都存储在 etcd,任何服务想要增删改查 etcd 的数据,都只能通过向 API Server 发起 RestFul 请求的方式来完成,咱们的 DiscoveryController 类获取所有 service 也是发请求到 API Server,由 API Server 从 etcd 中取得 service 的数据返回给 DiscoveryController:
如果您想弄清楚 service 数据在 etcd 中如何存储的,可以参考《查看 k8s 的 etcd 数据》一文,亲自动手连接 etcd 查看里面的 service 内容;
至此,spring-cloud-kubernetes 背后的三个关键知识点都已经学习了,下图算是对这些问题的一个小结:
希望以上的分析总结能对您有参考作用,由于对基本原理都已经了解,后面的 spring-cloud-kubernetes 实战可以更顺畅,也能从原理出发继续深入的分析和学习。
欢迎关注 InfoQ:程序员欣宸
版权声明: 本文为 InfoQ 作者【程序员欣宸】的原创文章。
原文链接:【http://xie.infoq.cn/article/1ed6280f5502dcda2c39f31a9】。文章转载请联系作者。
评论