擁抱Kubernetes,再見(jiàn)了Spring Cloud
相信很多Java從業(yè)者在熟悉了微服務(wù)開(kāi)發(fā)后,自以為用 Spring Cloud 已經(jīng)成功打造了微服務(wù)架構(gòu)帝國(guó),Java 已經(jīng)壟斷微服務(wù)領(lǐng)域,殊不知當(dāng)引入 k8s 后,Spring Cloud 卻和 Cloud Native 的生態(tài)發(fā)展脫軌了。
從 2013 年的 Spring Boot
2012年10月,Mike Youngstrom在Spring jira中創(chuàng)建了一個(gè)功能需求,要求在Spring框架中支持無(wú)容器Web應(yīng)用程序體系結(jié)構(gòu)。他建議通過(guò)main方法引導(dǎo)的Spring容器內(nèi)配置Web容器服務(wù)。這一需求促成了2013年初開(kāi)始的Spring Boot項(xiàng)目。2014年4月,Spring Boot 1.0.0發(fā)布。從那以后,一些Spring Boot小版本開(kāi)始出現(xiàn)。
- Spring Boot 1.1(2014年6月):改進(jìn)的模板支持,gemfire支持,elasticsearch和apache solr的自動(dòng)配置
- Spring boot 1.2(2015年3月):升級(jí)到servlet 3.1/tomcat 8/jetty 9和spring 4.1,支持banner/jms /SpringBoot Application注釋
- Spring boot 1.3(2016年12月):升級(jí)到spring4.2,新的spring-boot-devtools,緩存技術(shù)的自動(dòng)配置(ehcache,hazelcast,redis,guava和infinispan)以及完全可執(zhí)行的jar支持
- Spring boot 1.4(2017年1月):升級(jí)到spring 4.3,couchbase/neo4j支持,啟動(dòng)失敗分析和RestTemplateBuilder
- Spring boot 1.5(2017年2月):支持kafka /ldap,第三方庫(kù)升級(jí),放棄對(duì)CRaSH支持和執(zhí)行器日志終端用以動(dòng)態(tài)修改應(yīng)用程序日志級(jí)別
- Spring boot的簡(jiǎn)便性使java開(kāi)發(fā)人員能夠快速大規(guī)模地應(yīng)用于項(xiàng)目。Spring boot可以說(shuō)是Java中開(kāi)發(fā)基于RESTful微服務(wù)Web應(yīng)用的最快方法之一。它也非常適合docker容器部署和快速原型設(shè)計(jì)
- Spring Boot 2.0.0,于2018年3月1日發(fā)布,新版本特點(diǎn)有:基于 Java 8,支持 Java 9;支持 Quartz 調(diào)度程序;支持嵌入式 Netty,Tomcat, Undertow 和 Jetty 均已支持 HTTP/2;執(zhí)行器架構(gòu)重構(gòu),支持 Spring MVC, WebFlux 和 Jersey;對(duì)響應(yīng)式編程提供最大支持;引入對(duì) Kotlin 1.2.x 的支持,并提供了一個(gè) runApplication 函數(shù),用Kotlin 通用的方式啟動(dòng) Spring Boot 應(yīng)用程序。
一直到 Spring Cloud,第一批選型它的大公司很早就構(gòu)建出了完整微服務(wù)生態(tài),很多解決方案也被開(kāi)源,很多坑點(diǎn)已被國(guó)內(nèi)巨頭踩完所以相當(dāng)穩(wěn)定。對(duì)于很多想要使用微服務(wù)架構(gòu)的中小公司,這絕對(duì)是最佳進(jìn)場(chǎng)時(shí)機(jī),直接使用 Spring Cloud 全家桶,絕對(duì)是穩(wěn)定而正確的微服務(wù)架構(gòu)選擇。
但當(dāng)你所在公司引入 k8s 后,就變天了。
k8s 和 Spring Cloud 的激烈沖突
Java 生態(tài)的 Spring Cloud 可謂是迄今最完整的微服務(wù)框架,基本滿(mǎn)足所有微服務(wù)架構(gòu)需求,網(wǎng)上教程也不勝枚舉。但也因?yàn)?Spring Cloud 生態(tài)過(guò)于完整,而如今 k8s 又大行其道,當(dāng)我們把基于 Spring Cloud 開(kāi)發(fā)的服務(wù)放到 k8s 后, 一些機(jī)制就不受 k8s 生態(tài)管控了。
因?yàn)閺臄U(kuò)展部署、運(yùn)維角度出發(fā)的 k8s,在最原始容器、應(yīng)用部署及網(wǎng)絡(luò)層管理的基礎(chǔ)上,已逐步實(shí)現(xiàn)并貼近應(yīng)用層的需要,一些微服務(wù)架構(gòu)下的基礎(chǔ)需求(如:Service Discovery、API Gateway 等)開(kāi)始直接或間接被納入 k8s 生態(tài)。導(dǎo)致雙方有很多組件功能重疊,只能擇一而終。比如一旦你選了 Spring Cloud 的解決方案,就得放棄 k8s 那邊的機(jī)制。
Spring Cloud 官方提供的解決方案
為解決該問(wèn)題,官方在 Github 上提供了開(kāi)源方案,說(shuō)明如何以 Spring Cloud 整合 Kubernetes 生態(tài)下的元件,主要討論從原本組件架構(gòu)過(guò)度并一直到 Kubernetes 原生環(huán)境后的處理方法
https://github.com/spring-cloud/spring-cloud-kubernetes
該解決方案重點(diǎn)如下:
服務(wù)發(fā)現(xiàn) (Service Discovery)
Spring Cloud 的經(jīng)典解決方案:Netflix Eureka、Alibaba Nacos。主要原理都是在服務(wù)部署時(shí),去注冊(cè)自己的服務(wù),讓其他服務(wù)可檢索到自己。
- spring.cloud.service-registry.auto-registration.enabled
- @EnableDiscoveryClient(autoRegister=false)
但在 k8s ,服務(wù)的注冊(cè)和查詢(xún)由 Service 元件負(fù)責(zé),其連線名稱(chēng),是利用內(nèi)部 DNS 實(shí)現(xiàn)。這代表我們要將服務(wù)發(fā)現(xiàn)功能,接上 k8s 的 Service 機(jī)制。為達(dá)成目的,方案中提供了 DiscoveryClient 組件,讓基于 Spring Cloud 所開(kāi)發(fā)的程序可方便查詢(xún)其他服務(wù)。使用了 Kubernetes 原生的服務(wù)發(fā)現(xiàn),才能被 Istio 追蹤,未來(lái)才能納入 Service Mesh 的管控。
配置管理 (Configuration Management)
Spring Cloud 的解決方案:spring-cloud-config。但在 Kubernetes 上,有 ConfigMap 和 Secret 可使用,而且通常還會(huì)搭配 Vault 管理敏感配置。
而該方案提供了 ConfigMapPropertySource 和 SecretsPropertySource,來(lái)存取 Kubernetes 上的 ConfigMap 和 Secret。
負(fù)載均衡和熔斷器 (Load Balancing & Circuit Breaker)
Spring Cloud原有方案:Netflix Ribbon 和 Hystrix,但在 k8s 有 Service 實(shí)現(xiàn)負(fù)載均衡,以及 Istio 可實(shí)現(xiàn)熔斷器,開(kāi)發(fā)者只需專(zhuān)注 crud。由于負(fù)載均衡和熔斷器會(huì)依賴(lài)服務(wù)發(fā)現(xiàn)機(jī)制,因此 Ribbon 和 Hytrix 原先的功能在 k8s 原生環(huán)境下失效。該解決方案內(nèi)雖然有提到一些關(guān)于 Ribbon 整合 Kubernetes 原生環(huán)境的實(shí)現(xiàn),但相關(guān)鏈接已消失,應(yīng)該是放棄了。所以推薦避免使用客戶(hù)端的負(fù)載均衡和熔斷器。
Spring Cloud V.S k8s 重疊方案

我們當(dāng)然也能完全不理會(huì) k8s 原生組件,完全采用 Spring Boot 和 Spring Cloud 的解決方案,只把 k8s 當(dāng)做部署應(yīng)用的工具和平臺(tái)。但顯然在未來(lái),Service Mesh 及其通用的 Cloud Native 技術(shù)發(fā)展,就會(huì)和Spring Cloud脫軌,無(wú)法再和我們的應(yīng)用深度整合。
相比于 Spring Cloud 生態(tài)都只能使用 Java , k8s 生態(tài)的發(fā)展和設(shè)計(jì)更為通用且廣泛,一些 Spring Cloud 內(nèi)的元件功能,在 Kubernetes 除了包含支援以外,甚至有更多的整合和考量及延伸的功能。由于 CNCF 的推波助瀾及更多國(guó)際大廠投入,新工具、運(yùn)維方法、整合能力層出不窮。因此,在選型微服務(wù)架構(gòu)時(shí),k8s 的各種原生解決方案,都需要被放入評(píng)估考量中。目前網(wǎng)絡(luò)上很多 Spring Boot 和 Spring Cloud 的很多已經(jīng)過(guò)時(shí),而且都沒(méi)整合 k8s,與當(dāng)下主流的基礎(chǔ)設(shè)施環(huán)境有落差,學(xué)習(xí)時(shí)都要斟酌。