spring-cloud-kubernetes背后的三個關(guān)鍵知識點

      網(wǎng)友投稿 840 2025-03-31

      歡迎訪問我的GitHub


      這里分類和匯總了欣宸的全部原創(chuàng)(含配套源碼):https://github.com/zq2599/blog_demos

      本篇概覽

      在《你好spring-Cloud-Kubernetes》一文中,對spring-Cloud-Kubernetes這個SpringCloud官方kubernetes服務(wù)框架有了基本了解,今天來小結(jié)此框架涉及的關(guān)鍵技術(shù),為后面的深入學(xué)習(xí)做準備;

      概覽

      總結(jié)下來有三個關(guān)鍵知識點需要深入理解:

      DiscoveryClient是個接口,對應(yīng)的實現(xiàn)類是哪個?

      discoveryClient.getServices()方法取得了kubernetes的service信息,這背后的機制是什么?java應(yīng)用是怎樣取得所在kubernetes的服務(wù)信息的?

      kubernetes的service信息存在哪里?如何將這些信息給出去?

      接下來我們逐一分析每個知識點;

      DiscoveryClient接口的實現(xiàn)類實例從何而來

      先來回顧一下上一章的DiscoveryController.java的內(nèi)容:

      @RestController public class DiscoveryController { @Autowired private DiscoveryClient discoveryClient; /** * 探針檢查響應(yīng)類 * @return */ @RequestMapping("/health") public String health() { return "health"; } /** * 返回遠程調(diào)用的結(jié)果 * @return */ @RequestMapping("/getservicedetail") public String getUri( @RequestParam(value = "servicename", defaultValue = "") String servicename) { return "Service [" + servicename + "]'s instance list : " + JSON.toJSONString(discoveryClient.getInstances(servicename)); } /** * 返回發(fā)現(xiàn)的所有服務(wù) * @return */ @RequestMapping("/services") public String services() { return this.discoveryClient.getServices().toString() + ", " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); } }

      上述代碼中,我們并沒有寫創(chuàng)建DiscoveryClient實例的代碼,discoveryClient從何而來?

      這一切,要從DiscoveryController.java所在項目的pom.xml說起;

      在pom.xml中,有對spring-cloud-kubernetes框架的依賴配置:

      org.springframework.cloud spring-cloud-kubernetes-discovery 1.0.1.RELEASE

      打開spring-cloud-kubernetes-discovery的源碼,地址是:https://github.com/spring-cloud/spring-cloud-kubernetes/tree/master/spring-cloud-kubernetes-discovery ,在這個工程中發(fā)現(xiàn)了文件spring.factories:

      spring容器啟動時,會尋找classpath下所有spring.factories文件(包括jar文件中的),spring.factories中配置的所有類都會實例化,我們在開發(fā)springboot時常用到的XXX-starter.jar就用到了這個技術(shù),效果是一旦依賴了某個starter.jar很多功能就在spring初始化時候自動執(zhí)行了(例如mysql的starter,啟動時會連接數(shù)據(jù)庫),關(guān)于此技術(shù)的詳情,請參考以下三篇文章:

      《自定義spring boot starter三部曲之一:準備工作》

      《自定義spring boot starter三部曲之二:實戰(zhàn)開發(fā)》

      《自定義spring boot starter三部曲之三:源碼分析spring.factories加載過程》

      spring.factories文件中有兩個類:KubernetesDiscoveryClientAutoConfiguration和KubernetesDiscoveryClientConfigClientBootstrapConfiguration都會被實例化;

      先看KubernetesDiscoveryClientConfigClientBootstrapConfiguration,很簡單的源碼,KubernetesAutoConfiguration和KubernetesDiscoveryClientAutoConfiguration這兩個類會被實例化:

      /** * Bootstrap config for Kubernetes discovery config client. * * @author Zhanwei Wang */ @Configuration @ConditionalOnProperty("spring.cloud.config.discovery.enabled") @Import({ KubernetesAutoConfiguration.class, KubernetesDiscoveryClientAutoConfiguration.class }) public class KubernetesDiscoveryClientConfigClientBootstrapConfiguration { }

      在KubernetesAutoConfiguration的源碼中,會實例化一個重要的類:DefaultKubernetesClient,如下:

      @Bean @ConditionalOnMissingBean public KubernetesClient kubernetesClient(Config config) { return new DefaultKubernetesClient(config); }

      再看KubernetesDiscoveryClientAutoConfiguration源碼,注意

      kubernetesDiscoveryClient

      方法,這里面實例化了DiscoveryController所需的DiscoveryClient接口實現(xiàn),還要重點關(guān)注的地方是KubernetesClient參數(shù)的值,是上面提到的DefaultKubernetesClient對象:

      @Bean @ConditionalOnMissingBean @ConditionalOnProperty(name = "spring.cloud.kubernetes.discovery.enabled", matchIfMissing = true) public KubernetesDiscoveryClient kubernetesDiscoveryClient(KubernetesClient client, KubernetesDiscoveryProperties properties, KubernetesClientServicesFunction kubernetesClientServicesFunction, DefaultIsServicePortSecureResolver isServicePortSecureResolver) { return new KubernetesDiscoveryClient(client, properties, kubernetesClientServicesFunction, isServicePortSecureResolver); }

      至此,第一個問題算是弄清楚了:我們編寫的DiscoveryController類所需的DiscoveryClient接口實現(xiàn)類是KubernetesDiscoveryClient,用到的是spring規(guī)范中的spring.factories

      另外有一點很重要,下面要用到的:KubernetesDiscoveryClient有個成員變量是KubernetesClient,該變量的值是DefaultKubernetesClient實例;

      接下來看第二個問題;

      java應(yīng)用怎么能取得所在kubernetes的服務(wù)信息

      看看DiscoveryController是如何獲取所在kubernetes的服務(wù)信息的:

      @RequestMapping("/services") public String services() { return this.discoveryClient.getServices().toString() + ", " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); }

      如上所示,

      discoveryClient.getServices()

      spring-cloud-kubernetes背后的三個關(guān)鍵知識點

      方法返回了所有kubernetes的服務(wù)信息;

      discoveryClient對應(yīng)的類是spring-cloud-kubernetes項目的KubernetesDiscoveryClient.java,看方法:

      public List getServices(Predicate filter) { return this.kubernetesClientServicesFunction.apply(this.client).list().getItems() .stream().filter(filter).map(s -> s.getMetadata().getName()) .collect(Collectors.toList()); }

      這段代碼的關(guān)鍵在于

      this.kubernetesClientServicesFunction.apply(this.client).list()

      ,先看KubernetesClientServicesFunction實例的初始化過程,在KubernetesDiscoveryClientAutoConfiguration類中:

      @Bean public KubernetesClientServicesFunction servicesFunction( KubernetesDiscoveryProperties properties) { if (properties.getServiceLabels().isEmpty()) { return KubernetesClient::services; } return (client) -> client.services().withLabels(properties.getServiceLabels()); }

      KubernetesClientServicesFunction是個lambda表達式,用于KubernetesClient的時候,返回KubernetesClient.services()的結(jié)果,如果指定了標簽過濾,就用指定的標簽來做過濾(也就是kubernetes中的標簽選擇器的效果)

      因此,數(shù)據(jù)來源其實就是上面的

      this.client

      ,調(diào)用其services方法的返回結(jié)果;

      KubernetesDiscoveryClient.getServices方法中的

      this.client

      是什么呢?分析前面的問題時已經(jīng)提到過了,就是DefaultKubernetesClient類的實例,所以,此時要去看DefaultKubernetesClient.services方法,發(fā)現(xiàn)client是ServiceOperationsImpl實例:

      @Override public MixedOperation> services() { return new ServiceOperationsImpl(httpClient, getConfiguration(), getNamespace()); }

      接著看ServiceOperationsImpl.java,我們關(guān)心的是它的list方法,此方法在父類BaseOperation中找到:

      public L list() throws KubernetesClientException { try { HttpUrl.Builder requestUrlBuilder = HttpUrl.get(getNamespacedUrl()).newBuilder(); String labelQueryParam = getLabelQueryParam(); if (Utils.isNotNullOrEmpty(labelQueryParam)) { requestUrlBuilder.addQueryParameter("labelSelector", labelQueryParam); } String fieldQueryString = getFieldQueryParam(); if (Utils.isNotNullOrEmpty(fieldQueryString)) { requestUrlBuilder.addQueryParameter("fieldSelector", fieldQueryString); } Request.Builder requestBuilder = new Request.Builder().get().url(requestUrlBuilder.build()); L answer = handleResponse(requestBuilder, listType); updateApiVersion(answer); return answer; } catch (InterruptedException | ExecutionException | IOException e) { throw KubernetesClientException.launderThrowable(forOperationType("list"), e); } }

      展開上面代碼的handleResponse方法,可見里面是一次http請求,至于請求的地址,可以展開getNamespacedUrl()方法,里面調(diào)用的getRootUrl方法如下:

      public URL getRootUrl() { try { if (apiGroup != null) { return new URL(URLUtils.join(config.getMasterUrl().toString(), "apis", apiGroup, apiVersion)); } return new URL(URLUtils.join(config.getMasterUrl().toString(), "api", apiVersion)); } catch (MalformedURLException e) { throw KubernetesClientException.launderThrowable(e); } }

      可見最終的地址應(yīng)該是:

      xxxxxx/api/v1

      或者

      xxxxxx/apis/xx/v1

      這樣的字符串。

      這樣的字符串意味著什么呢?

      這是訪問kubernetes的API Server時用到的URL標準格式

      ,有關(guān)API Server服務(wù)的詳情請參考官方文檔,地址是:https://kubernetes.io/docs/reference/using-api/api-concepts/

      如下圖,用OperationSupport類的源碼和官方文檔的URL截圖做個對比,大家就一目了然了:

      還剩個小問題,上圖中,OperationSupport類的成員變量resourceT是什么值?官方文檔示例中是"pods",在獲取service的時候又該是多少呢?順著源碼一路找下去,找到了類的構(gòu)造方法,如下所示,第五個參數(shù)就是resourceT,這里直接被寫死為"services":

      public ServiceOperationsImpl(OkHttpClient client, Config config, String apiVersion, String namespace, String name, Boolean cascading, Service item, String resourceVersion, Boolean reloadingFromServer, long gracePeriodSeconds, Map labels, Map labelsNot, Map labelsIn, Map labelsNotIn, Map fields) { super(client, config, null, apiVersion, "services", namespace, name, cascading, item, resourceVersion, reloadingFromServer, gracePeriodSeconds, labels, labelsNot, labelsIn, labelsNotIn, fields); }

      至此,第二個問題“controller中用到的kubernetes服務(wù)數(shù)據(jù)從何而來"已經(jīng)清楚了:最終是調(diào)用okhttp的newCall方法向kubernetes的API Server發(fā)起http請求,獲取service資源的數(shù)據(jù)列表;

      接下來,該最后一個問題了;

      API Server收到請求后做了什么?

      關(guān)于API Server如何響應(yīng)各類http請求,本文只做一些簡單的說明,詳細信息還請參考官方文檔,地址是:https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/

      如下圖所示,在kubernetes環(huán)境中,pod、service這些資源的數(shù)據(jù)都存儲在etcd,任何服務(wù)想要增刪改查etcd的數(shù)據(jù),都只能通過向API Server發(fā)起RestFul請求的方式來完成,咱們的DiscoveryController類獲取所有service也是發(fā)請求到API Server,由API Server從etcd中取得service的數(shù)據(jù)返回給DiscoveryController:

      如果您想弄清楚service數(shù)據(jù)在etcd中如何存儲的,可以參考《查看k8s的etcd數(shù)據(jù)》一文,親自動手連接etcd查看里面的service內(nèi)容;

      至此,spring-cloud-kubernetes背后的三個關(guān)鍵知識點都已經(jīng)學(xué)習(xí)了,下圖算是對這些問題的一個小結(jié):

      希望以上的分析總結(jié)能對您有參考作用,由于對基本原理都已經(jīng)了解,后面的spring-cloud-kubernetes實戰(zhàn)可以更順暢,也能從原理出發(fā)繼續(xù)深入的分析和學(xué)習(xí)。

      歡迎關(guān)注華為云博客:程序員欣宸

      學(xué)習(xí)路上,你不孤單,欣宸原創(chuàng)一路相伴…

      Kubernetes Spring Spring Cloud

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:如何在wps設(shè)置標題水平線
      下一篇:wps2019如何生成二維碼
      相關(guān)文章
      亚洲精品动漫人成3d在线| 亚洲日本在线免费观看| 久久水蜜桃亚洲av无码精品麻豆| 亚洲高清国产拍精品26U| 狠狠综合亚洲综合亚洲色| 国产成人亚洲综合网站不卡| 国产成人精品日本亚洲18图| 亚洲一区中文字幕在线电影网| 亚洲视频在线免费观看| 亚洲国产成人高清在线观看| 亚洲女人被黑人巨大进入| 亚洲男人的天堂在线va拉文| 亚洲人成人网站在线观看| 亚洲国产精品激情在线观看 | 亚洲精品在线不卡| 91亚洲自偷手机在线观看| 亚洲伊人久久大香线蕉苏妲己| 91亚洲一区二区在线观看不卡| 亚洲国产精彩中文乱码AV| 亚洲日本中文字幕| 亚洲网红精品大秀在线观看| 亚洲综合色一区二区三区小说| 亚洲三级视频在线观看| 亚洲最大无码中文字幕| 久久亚洲欧美国产精品| 久久精品国产亚洲AV电影网| 亚洲黄片毛片在线观看| 亚洲日韩aⅴ在线视频| 亚洲AV第一页国产精品| 亚洲国产日韩在线人成下载| 亚洲综合色一区二区三区| 国产精品亚洲专区无码牛牛 | 亚洲综合男人的天堂色婷婷| 亚洲ts人妖网站| 亚洲AV女人18毛片水真多| 亚洲精品国自产拍在线观看| 亚洲精品国产精品乱码视色| 777亚洲精品乱码久久久久久 | 亚洲欧美熟妇综合久久久久| 国产成人亚洲精品蜜芽影院| 亚洲欧洲日产国码无码久久99|