1. 程式人生 > >基於Spring Cloud的微服務實踐

基於Spring Cloud的微服務實踐

內容包含微服務框架選型、CI/CD、容器編排的經驗,旨在幫助大家低成本、快速落地微服務,在刀刀見血的網際網路大潮中,快速迭代,快速交付。

相關趨勢圖

首先給大家看一張百度指數上,關於微服務、Spring Boot、Spring Cloud、Dubbo的趨勢圖:

從圖中可見,Dubbo的搜尋量增勢放緩,Spring Boot從16年中下旬開始發力,一路高漲。學習了Spring Boot再學習Spring Cloud幾乎順理成章。

Spring Boot旨在解決Spring越來越臃腫的全家桶方案的配置地獄(諷刺的是,Spring剛出道是扯著輕量化解決方案大旗一路衝殺,現在自己也開始慢慢胖起來了),提供了很多簡單易用的starter。特點是預定大於配置。

Dubbo放緩是源於,阿里巴巴中間斷更將近三年(dubbo-2.4.11 2014-10-30, dubbo-2.5.4 2017-09-07),很多依賴框架和技術都較為陳舊,也不接納社群的PR(當然,最近開始恢復更新,後面會有說到),導致噹噹另起爐灶,fork了一個: https://github.com/dangdangdotcom/dubbox(現在已斷更)。

而且Dubbo僅相當於Spring Cloud的一個子集,可參考文章《微服務架構的基礎框架選擇:Spring Cloud還是Dubbo?》:http://blog.csdn.net/kobejayandy/article/details/52078275

另外我們可以看看k8s、kubernetes 、docker的搜尋趨勢:

上面兩圖意在說明,微服務相關和容器相關越來越流行了,不再是一個特別新的、不成熟的技術。那單體服務和微服務的對比如何呢?

微服務 vs. 單體應用

單體應用好處:

  1. 開發簡單

  2. 容易測試

  3. 易於部署

  4. 事務回滾容易

  5. 無分散式管理,呼叫開銷

  6. 重複功能/程式碼較少

單體應用缺點:

  1. 迭代緩慢

  2. 維護困難

  3. 持續部署困難:微小改動,必須重啟,不相干功能無法提供服務

  4. 牽一髮而動全身:依賴項衝突,變更後,需要大量測試,防止影響其他功能

  5. 基礎語言、框架升級緩慢

  6. 框架語言單一,無法靈活選用

微服務好處:

  1. 敏捷性:按功能拆分,快速迭代

  2. 自主性:團隊技術選型靈活(PHP、python、java、C#、nodejs、golang),設計自主

  3. 可靠性:微服務故障隻影響此服務消費者,而單體式應用會導致整個服務不可用

  4. 持續整合持續交付

  5. 可擴充套件性:熱點功能容易擴充套件

微服務的缺點:

  1. 效能降低:服務間通過網路呼叫

  2. 管理難度增大:增加了專案的複雜性

  3. 事務一致性

擴充套件閱讀《Introduction to Microservices》:https://www.nginx.com/blog/introduction-to-microservices/

框架選型

下面分享一下我司在落地微服務時的框架選型方面的一些經驗。

我們公司主要使用java,所以決定使用Spring框架中的Spring Cloud作為微服務基礎框架,但是原生Spring Cloud學習曲線比較陡峭,需要學習feign、zuul、eureka、hystrix、zipkin、ribbon…需要老司機坐副駕駛,不然容易翻車。

最後考慮團隊的技術水平和學習成本,多方面考察,我們最後採用了國外的開源框架JHipster http://www.jhipster.tech/。其實國內用Dubbo的較多,用JHipster的較少。我們不用Dubbo的原因,前面提到過,一個是中間斷更,以及阿里說不更就不更的優良傳統,還有Dubbo從功能來說,只是Spring Cloud的一個子集。

從JHipster官方資料看,登記在冊的使用 jhipster的企業有224家,其中不乏Google、Adobe一類的大廠。可參見 http://www.jhipster.tech/companies-using-jhipster/

此處列舉一下JHipster的技術棧(開箱即用):

客戶端技術棧:

  • angular4,5 or angularv1.x

  • Bootstrap

  • HTML5 Boilerplate

  • 相容IE11+及現代瀏覽器

  • 支援國際化

  • 支援sass

  • 支援spring websocket

  • 支援yarn、bower管理js庫

  • 支援webpack、gulp.js構建,優化,應用

  • 支援Karma、Headless Chrome 和 Protractor 進行前端單元測試測試

  • 支援Thymeleaf 模板引擎,從服務端渲染頁面

服務端技術棧:

  • 支援spring boot 簡化spring配置

  • 支援maven、gradle,構建、測試、執行程式

  • 支援多配置檔案(預設dev,prod)

  • spring security

  • spring mvc REST + jackson

  • spring websocket

  • spring data jpa + Bean Validation

  • 使用liquibase管理資料庫表結構變更版本

  • 支援elasticsearch,進行應用內搜素

  • 支援mongoDB 、Couchbase、Cassandra等NoSQL

  • 支援h2db、pgsql、mysql、meriadb、sqlserver、oracle等關係型sql

  • 支援kafka mq

  • 使用 zuul或者traefik作為http理由

  • 使用eureka或consul進行服務發現

  • 支援ehcache、hazelcast、infinispan等快取框架

  • 支援基於hazelcast的httpsession叢集

  • 資料來源使用HikariCP連線池

  • 生成Dockerfile、docker-compose.yml

  • 支援雲服務商AWS、Cloud Foundry、Heroku、Kubernetes、Openshift、Docker …

  • 支援統一配置中心

不過真正用了後,就會發現,這個列表不全,JHipster支援的不止列表中描述的這些,大家也可以參考我以前寫的《JHipster開發筆記》: https://jh.jiankangsn.com/

JHipster是基於yoman的一個快速開發的腳手架(國內前幾年流行的名字叫程式碼生成器),需要nodejs 環境 ,並且使用yarn搭建環境。當然不會也沒事,它非常簡單,如果實在想用,可以用《JHipster Online》:https://start.jhipster.tech/。類似Spring的http://start.spring.io/

值得一提的是JHipster也支援通過JHipster rancher-compose命令來生成rancher-compose.yml和docker-compose.yml,具體可參考《[BETA] Deploying to Rancher》:http://www.jhipster.tech/rancher/

對於小團隊落地微服務,可以考慮使用JHipster來生成專案,能夠極大的提高效率。基本上可以視作JHipster是一套基於Spring Boot的最佳實踐(不僅支援微服務,也支援單體式應用)。對於想學習Spring Boot或者Spring Cloud的也建議瞭解一下JHipster,好過獨自摸索。

JHipster依賴的技術框架版本基本都是最新穩定版,版本更新比較及時,基本上一月一個版本,對GitHub上的issues和PR響應比較及時(一般在24小時內)。

10分鐘搭建微服務

下面我將分享如何10分鐘搭建一套微服務(不含下載nodejs、安裝maven等準備環境的時間)。

安裝nodejs、yarn的指南可參見我在《JHipster開發筆記》中的一篇【安裝】:https://jh.jiankangsn.com/install.html

需要注意的是,如果是windows nodejs,需要安裝v7.x,因為註冊中心和閘道器需要用到[email protected],但是github上的node-sass的rebuild只有v7.x(process 51) 版本的,而自己構建太反人類了。如果是linux,可以嘗試高版本的,建議裝nodejs v7.x,除非你想玩刺激,自己build一個node-sass。

為了加速下載,建議用npm的淘寶映象:

安裝jdk8、maven、maven加速這些就不說了,可自行百度。

下載註冊中心

JHipster-registry github地址 :https://github.com/jhipster/jhipster-registry)

瀏覽器訪問 http://localhost:8761,初始使用者名稱密碼均為admin。

註冊中心的頁面

Spring Config Server,統一配置中心,可以統一管理不同環境的資料庫地址、使用者名稱、密碼等敏感資料。

JHipster Registry對應SC(Spring Cloud)的eurake+spring config server。

建立閘道器

建立api閘道器,參見

【Creating an application】:http://www.jhipster.tech/creating-an-app/

【The JHipster API Gateway】: http://www.jhipster.tech/api-gateway/

訪問http://localhost:8080/,預設使用者名稱密碼均為admin。

建立服務

建立服務可參考:http://www.jhipster.tech/creating-an-app/

訪問http://localhost:8080/#/docs 預設使用者名稱密碼均為 admin ,使用swagger管理api文件,開發時,僅需要新增對應的註解,即可自動生成文件,解決了傳統通過word、pdf等管理介面時,文件更新不及時等問題。並且可以通過try it直接呼叫介面,避免了介面除錯時使用curl、postman等工具。

至此,已經建立了一個簡單微服務(JHipster-registry是註冊中心,gateway是閘道器,foo是具體的功能模組)。

建立實體

JHipster支援通過命令列建立實體,也支援uml或jdl生成實體,為了省事,此處使用官方jdl-studio的預設jdl檔案https://start.jhipster.tech/jdl-studio/。

重啟foo服務,再次訪問http://localhost:8080/#/docs,發現多了很多介面

通過swagger ui,找到region-resource,找到POST /api/regions,建立一個名為test的regison。

try it out! ,然後瀏覽器開啟h2 資料庫http://localhost:8081/h2-console

查詢REGION表,資料已經插入成功。

至此,一個雖然簡單、但是可用的微服務已經弄好。

將服務釋出到Rancher

JHipster支援釋出到Cloud Foundry、Heroku、Kubernetes、Openshift、Rancher、AWS、Boxfuse。

我們建議使用Rancher,因為Cloud Foundry 、Heroku、AWS、Boxfuse都是雲環境,而k8s和openshift origin太複雜了,而Rancher則很容易上手,功能完備,也是完全開源,其聯合創始人還是CNCF的理事會成員。

服務釋出可以參見文件:http://www.jhipster.tech/rancher/

RANCHER-COMPOSE.YML

DOCKER-COMPOSE.YML

docker-compose.yml中給的JHipster-registry是本地模式的,可以根據註釋部分內容,改成從Git拉。好處是維護方便,壞處是容易造成單點故障。使用Git模式,就可以將registry-config-sidekick 部分去掉。

JHipster使用liquibase進行資料庫版本管理,便於資料庫版本變更記錄管理和遷移。(rancher server也用的liquibase)

把docker-compose.yml和rancher-compose.yml貼到rancher上,就能建立一個應用stack了。

不過,好像漏了點啥?少了CICD。Rancher和docker的compsoe.yml有了,但是,還沒構建映象呢,映象還沒push到registry呢,對吧?

CI/CD

自建GitLab

我司用GitLab管理原始碼,我在Docker Hub上釋出了一個漢化的GitLab:https://hub.docker.com/r/gitlab/gitlab-ce/tags/

如果要用官方映象,參見https://hub.docker.com/r/gitlab/gitlab-ce/tags/

GitLab CI

我們的CI用的是GitLab-CI,參見【GitLab Continuous Integration (GitLab CI)】: https://docs.gitlab.com/ce/ci/README.html

為啥不用Jenkins?這個蘿蔔白菜各有所愛,我是出於壓縮技術棧的考慮:

  1. GitLab-CI夠簡單,也夠用

  2. 它和GitLab配套,不用多學習Jenkins,畢竟多一套,就多一套的學習成本

搭建映象伺服

老牌sonatype nexus oss可以管理 Bower、Docker、Git LFS、Maven、npm、NuGet、PyPI、Ruby Gems、Yum Proxy,功能豐富:https://www.sonatype.com/download-oss-sonatype

GitLab Container Registry administration,GitLab Registry跟GitLab整合,不需要額外安裝服務:https://docs.gitlab.com/ce/administration/container_registry.html#gitlab-container-registry-administration

Harbor應用商店就有,安裝方便,號稱企業級registry,功能強大:http://vmware.github.io/harbor/rancher

如何選擇?還是那句話,看需求。我司有部署maven和npm的需要,所以用了nexus oss,順便管理docker registry。

Service Mesh——下一代微服務

我司是從16年八九月份開始拆分單體服務,彼時國內Spring Cloud,微服務等相關資料較少,國內流行dubbo(那會已經斷更1年多了,雖然現在復更,但是對其前景不太看好)。

從17年開始,圈內討論Spring Cloud的漸漸多起來了,同時市面上也有了介紹Spring Cloud的書籍,比如周立的《Spring Cloud與Docker微服務架構實戰》, 翟永超的《Spring Cloud微服務實戰》等。

但是用了Spring Cloud後,感覺Spring Cloud太複雜了(如果用了JHipster情況會好點),並沒有實現微服務的初衷:

  1. 跟語言,框架無關:侷限於java

  2. 隱藏底層細節,需要學習zuul路由,eureka註冊中心,configserver配置中心,需要熔斷,降級,需要實現分散式跟蹤…

在這種情況下,16年,國外buoyant公司提出Service Mesh概念,基於scala建立了linkerd專案。Service Mesh 的設想就是,讓開發人員專注於業務,不再分心於基礎設施。

目前主流框架:

  • istio:背靠google,ibm,後臺硬,前景廣闊

  • conduit:跟linkerd是一個公司的,使用Rust語言開發,proxy消耗不到10M記憶體,p99控制在毫秒內

  • linkerd:商用企業較多,國內我知道的有豆瓣

  • envoy:國內騰訊在用

其中istio和conduit都不太成熟,而linkerd和envoy都有商用案例,較為成熟。長遠來看,我更看好istio和conduit。

對Dubbo的老使用者來說也有個好訊息,據說 Dubbo3 將相容2,並且支援Service Mesh,支援反應式程式設計。

結語

建議大家根據公司、團隊實際情況理性選擇框架,目前Service Mesh還處於墾荒階段,而Spring Cloud或者Dubbo還沒到徹底過時的程度,建議持續關注,不建議立刻上馬。

如果已經落地了相關的微服務技術,不要盲目跟風,在可接受學習成本和開發成本情況下,可以考慮研究一下Service Mesh。

如果使用的是Spring框架的話,建議拋開Spring Cloud,直接Spring Boot + Service Mesh,更清爽一些。

擴充套件閱讀資料:

1. 【官方文件|ServiceMesh服務網格Istio面板元件&設計目標】 http://blog.shurenyun.com/untitled-102/

2. 【演講實錄 | Service Mesh 時代的選邊與站隊(附PPT下載)】 http://www.servicemesh.cn/?/article/25

3. 【Service Mesh:下一代微服務】 https://servicemesh.gitbooks.io/awesome-servicemesh/mesh/2017/service-mesh-next-generation-of-microservice/

Q&A

Q:你們是選擇使用consul還是JHipster-register?

A:我們用的是JHipster-registry,核心是eureka,但是有問題,服務狀態廣播需要心跳時間,在升級服務的時候,容易丟請求,建議用consul或者類似kong這種的,或者用service mesh,比如istio,定義流量策略。

Q:Spring Boot+k8s進行微服務改造可行不?先來簡單的。

A:當然可行,如果可以,建議spring boot+service mesh(e.g. istio)+k8s,皇家拍檔,類似咖啡跟咖啡伴侶。

Q:請問貴司是如何定製JHipster的呢?或者有沒有什麼好的建議。

A:JHipster本身是很open的,通過我貼的技術棧基本滿足普通開發需求了,而且JHipster是基於Spring Boot/Spring Cloud,而Spring Boot又基於Spring 。所以理論上沒有整合壓力,或者說是定製壓力。

Q:ORM能隨意切換MyBais嗎?

A:可以換,沒問題。

Q:Spring Cloud裡面的元件和k8s功能有重疊的部分,可不可以相互用下?

A:跟上題一樣,只要能跟Spring整合,就能跟JHipster整合。如果沒用SC或者JHipster,我是建議用Springboot+Service Mesh+k8s。不過只從開發體驗來說,用JHipster和Service Mesh,差別不大(JHipster隱藏了很多SC的底層細節)。

Q:除了java以外的如何整合呢?

A:如果非java語言的話,建議Service mesh+k8s,可以參考微博的 Motan。

Q:資料庫版本管理,有什麼好的方式?

A:資料庫版本管理,目前比較流行的有 liquibase(JHipster 預設使用,Rancher也用的liquibase) 與flyway。

Q:JHipster 預設使用JPA ,你安利案例中,你們是使用JPA 還是使用別的?如mybatis等。

A:JHipster預設使用JPA沒錯,但是在一些簡單CURD中,已經夠用了,稍微複雜點的,可以用@Query,再複雜點的,可以用【querydsl】 http://www.querydsl.com/ 。逆天難度的,可以國產的mybatis-plus。還是要看困難等級。50%的情況,用JPA就夠了,比如 findAll(),不用寫任何實現,findByName(String name)。

Q:在安利案例中,有是使用uaa做 Oauth2 伺服器嗎?

A:【uaa】http://www.jhipster.tech/using-uaa/

。從JHipster官方來看,建議用OIDC。當然也支援jwt。OIDC openID Connect:http://www.jhipster.tech/security/

Q:SC的通訊效率是不是有問題?沒有Dubbo快

A:其實,SC用的是RESTful 基於http,Dubbo是rpc。雖然rest慢一些,更佔頻寬一些,但是,好處是除錯方便,方便對接,捫心自問一下,你們的qps,真到了rest成瓶頸的級別了麼?

Q:java與jhipster在CICD持續整合,結合K8S如何做的,具體的例子有沒有

A:k8s CD:http://www.jhipster.tech/kubernetes/

Q:是不是k8s安裝了linkerd元件就有service mesh了?

A:建議 k8s + istio conduit

linkerd基於scala,效能有點差,當然目前也是商用最多的方案。同時 service mesh,也是 linkerd提出的概念,service mesh類似微服務,只是一個概念,具體實現,目前主流的有istio、conduit、linkerd、envoy。

Q:scala效能不算差吧?跟java是同樣的。

A:對啊,基於jvm,而conduit 使用Rust語言(可以理解成c++)開發,proxy消耗不到10M記憶體,p99控制在毫秒內,而 linkerd一般300-500M,不是一個量級。