spring-cloud-kubernetes的三個(gè)關(guān)鍵知識(shí)點(diǎn)是什么

本篇內(nèi)容介紹了“spring-cloud-kubernetes的三個(gè)關(guān)鍵知識(shí)點(diǎn)是什么”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

創(chuàng)新互聯(lián)主營(yíng)江夏網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,APP應(yīng)用開(kāi)發(fā),江夏h5小程序定制開(kāi)發(fā)搭建,江夏網(wǎng)站營(yíng)銷(xiāo)推廣歡迎江夏等地區(qū)企業(yè)咨詢

DiscoveryClient接口的實(shí)現(xiàn)類(lèi)實(shí)例從何而來(lái)

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

@RestController
public class DiscoveryController {

    @Autowired
    private DiscoveryClient discoveryClient;

    /**
     * 探針檢查響應(yīng)類(lèi)
     * @return
     */
    @RequestMapping("/health")
    public String health() {
        return "health";
    }

    /**
     * 返回遠(yuǎn)程調(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());
    }
}

上述代碼中,我們并沒(méi)有寫(xiě)創(chuàng)建DiscoveryClient實(shí)例的代碼,discoveryClient從何而來(lái)?

這一切,要從DiscoveryController.java所在項(xiàng)目的pom.xml說(shuō)起;

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

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-kubernetes-discovery</artifactId>
  <version>1.0.1.RELEASE</version>
</dependency>
  1. 打開(kāi)spring-cloud-kubernetes-discovery的源碼,地址是:https://github.com/spring-cloud/spring-cloud-kubernetes/tree/master/spring-cloud-kubernetes-discovery ,在這個(gè)工程中發(fā)現(xiàn)了文件spring.factories: spring-cloud-kubernetes的三個(gè)關(guān)鍵知識(shí)點(diǎn)是什么

  2. spring容器啟動(dòng)時(shí),會(huì)尋找classpath下所有spring.factories文件(包括jar文件中的),spring.factories中配置的所有類(lèi)都會(huì)實(shí)例化,我們?cè)陂_(kāi)發(fā)springboot時(shí)常用到的XXX-starter.jar就用到了這個(gè)技術(shù),效果是一旦依賴了某個(gè)starter.jar很多功能就在spring初始化時(shí)候自動(dòng)執(zhí)行了(例如MySQL的starter,啟動(dòng)時(shí)會(huì)連接數(shù)據(jù)庫(kù))

  3. spring.factories文件中有兩個(gè)類(lèi):KubernetesDiscoveryClientAutoConfiguration和KubernetesDiscoveryClientConfigClientBootstrapConfiguration都會(huì)被實(shí)例化;

  4. 先看KubernetesDiscoveryClientConfigClientBootstrapConfiguration,很簡(jiǎn)單的源碼,KubernetesAutoConfiguration和KubernetesDiscoveryClientAutoConfiguration這兩個(gè)類(lèi)會(huì)被實(shí)例化:

/**
 * 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 {

}
  1. 在KubernetesAutoConfiguration的源碼中,會(huì)實(shí)例化一個(gè)重要的類(lèi):DefaultKubernetesClient,如下:

@Bean
@ConditionalOnMissingBean
public KubernetesClient kubernetesClient(Config config) {
	return new DefaultKubernetesClient(config);
}
  1. 再看KubernetesDiscoveryClientAutoConfiguration源碼,注意<font color="blue">kubernetesDiscoveryClient</font>方法,這里面實(shí)例化了DiscoveryController所需的DiscoveryClient接口實(shí)現(xiàn),還要重點(diǎn)關(guān)注的地方是KubernetesClient參數(shù)的值,是上面提到的DefaultKubernetesClient對(duì)象:

@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);
}
  1. 至此,第一個(gè)問(wèn)題算是弄清楚了:我們編寫(xiě)的DiscoveryController類(lèi)所需的DiscoveryClient接口實(shí)現(xiàn)類(lèi)是KubernetesDiscoveryClient,用到的是spring規(guī)范中的spring.factories

  2. 另外有一點(diǎn)很重要,下面要用到的:KubernetesDiscoveryClient有個(gè)成員變量是KubernetesClient,該變量的值是DefaultKubernetesClient實(shí)例;

接下來(lái)看第二個(gè)問(wèn)題;

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

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

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

如上所示,<font color="blue">discoveryClient.getServices()</font>方法返回了所有kubernetes的服務(wù)信息; 2. discoveryClient對(duì)應(yīng)的類(lèi)是spring-cloud-kubernetes項(xiàng)目的KubernetesDiscoveryClient.java,看方法:

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

這段代碼的關(guān)鍵在于<font color="blue">this.kubernetesClientServicesFunction.apply(this.client).list()</font>,先看KubernetesClientServicesFunction實(shí)例的初始化過(guò)程,在KubernetesDiscoveryClientAutoConfiguration類(lèi)中:

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

  return (client) -> client.services().withLabels(properties.getServiceLabels());
}

KubernetesClientServicesFunction是個(gè)lambda表達(dá)式,用于KubernetesClient的時(shí)候,返回KubernetesClient.services()的結(jié)果,如果指定了標(biāo)簽過(guò)濾,就用指定的標(biāo)簽來(lái)做過(guò)濾(也就是kubernetes中的標(biāo)簽選擇器的效果)

因此,數(shù)據(jù)來(lái)源其實(shí)就是上面的<font color="blue">this.client</font>,調(diào)用其services方法的返回結(jié)果; 3. KubernetesDiscoveryClient.getServices方法中的<font color="blue">this.client</font>是什么呢?分析前面的問(wèn)題時(shí)已經(jīng)提到過(guò)了,就是DefaultKubernetesClient類(lèi)的實(shí)例,所以,此時(shí)要去看DefaultKubernetesClient.services方法,發(fā)現(xiàn)client是ServiceOperationsImpl實(shí)例:

@Override
  public MixedOperation<Service, ServiceList, DoneableService, ServiceResource<Service, DoneableService>> services() {
    return new ServiceOperationsImpl(httpClient, getConfiguration(), getNamespace());
  }
  1. 接著看ServiceOperationsImpl.java,我們關(guān)心的是它的list方法,此方法在父類(lèi)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);
    }
  }

展開(kāi)上面代碼的handleResponse方法,可見(jiàn)里面是一次http請(qǐng)求,至于請(qǐng)求的地址,可以展開(kāi)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);
    }
  }

可見(jiàn)最終的地址應(yīng)該是:<font color="blue">xxxxxx/api/v1</font>或者<font color="blue">xxxxxx/apis/xx/v1</font>這樣的字符串。

這樣的字符串意味著什么呢?<font color="red">這是訪問(wèn)kubernetes的API Server時(shí)用到的URL標(biāo)準(zhǔn)格式</font>,有關(guān)API Server服務(wù)的詳情請(qǐng)參考官方文檔,地址是:https://kubernetes.io/docs/reference/using-api/api-concepts/

如下圖,用OperationSupport類(lèi)的源碼和官方文檔的URL截圖做個(gè)對(duì)比,大家就一目了然了: spring-cloud-kubernetes的三個(gè)關(guān)鍵知識(shí)點(diǎn)是什么 5. 還剩個(gè)小問(wèn)題,上圖中,OperationSupport類(lèi)的成員變量resourceT是什么值?官方文檔示例中是"pods",在獲取service的時(shí)候又該是多少呢?順著源碼一路找下去,找到了類(lèi)的構(gòu)造方法,如下所示,第五個(gè)參數(shù)就是resourceT,這里直接被寫(xiě)死為"services":

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

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

接下來(lái),該最后一個(gè)問(wèn)題了;

API Server收到請(qǐng)求后做了什么?

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

如下圖所示,在kubernetes環(huán)境中,pod、service這些資源的數(shù)據(jù)都存儲(chǔ)在etcd,任何服務(wù)想要增刪改查etcd的數(shù)據(jù),都只能通過(guò)向API Server發(fā)起RestFul請(qǐng)求的方式來(lái)完成,咱們的DiscoveryController類(lèi)獲取所有service也是發(fā)請(qǐng)求到API Server,由API Server從etcd中取得service的數(shù)據(jù)返回給DiscoveryController: spring-cloud-kubernetes的三個(gè)關(guān)鍵知識(shí)點(diǎn)是什么

“spring-cloud-kubernetes的三個(gè)關(guān)鍵知識(shí)點(diǎn)是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

網(wǎng)站名稱:spring-cloud-kubernetes的三個(gè)關(guān)鍵知識(shí)點(diǎn)是什么
文章網(wǎng)址:http://muchs.cn/article8/igeoop.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管用戶體驗(yàn)、網(wǎng)站排名、定制開(kāi)發(fā)、網(wǎng)站設(shè)計(jì)、外貿(mào)建站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司