1. 程式人生 > >Spring Cloud 微服務及相關技術總結

Spring Cloud 微服務及相關技術總結

    微服務,分散式架構。

    如果專案體量較大,比如大型電商專案,可以拆分出多個子模組比如處理商品、訂單、報表、活動等,各個模組負責各自的業務,解耦合,對開發、維護都有意義,就可以引入微服務架構了。微服務後,各服務之間的影響有效降低。試想一個大專案完全用一個工程去做,體量過於臃腫,或者以通過維護介面連線的方式去實現,是相當冗餘的事情。

    還有一種情形是,有些模組、元件在多個專案中有共通性,高複用性,那完全可以抽離出來形成服務模式,有效的提高了產出。    公司組織研究開發微服務架構Spring Cloud,著手各大專案的雲化。
Spring Cloud是基於Spring Boot實現的微服務架構。
我們從搭建springboot工程開始,組建各個小分隊研究各個模組:分別實現了:

1、使用GIT,GIT的好處程式碼的保護(本機與遠端)及實現開發分支化,很關鍵的一點是spring cloud對git有著很好的整合,尤其是在spring cloud config配置集中化環節。

2、SpringBoot工程 。在structs工程,每寫一個請求url還得配置一次,簡直繁瑣的XML配置,沒用spring mvc \boot 那你已經落伍很久了。spring boot 的出發點是配置簡約化,使大家把精力更多放在業務實現上。
plat\web層:controller\service\jsp&freemaker ; 

service層:evt\controller\service\dao(mapper、provider)\myBatis&hibernate。

3、基於Swagger介面服務。在介面成做相應的配置即可,在swagger 頁面中,自動呈現出具有rest風格的api文件,方便除錯。而且也對RestFul風格有很好的體現。java 介面實現RestFul(表現層、資源統一),請求參格式包括path、query、body等等。使用Http那一套請求規範,請求資源GET,建立資源POST,修改資源PUT,刪除DELETE,還有HEAD|OPTIONS等,而且響應標識使用標準的HTTPStatus,如請求ok 200、建立成功201,異常400等,資料格式使用JSON對前後端解析都方便。

4、服務治理中心Eurka 負責服務註冊與發現。服務治理應該是微服務的核心功能點了,每個微服務即是服務提供方也是服務呼叫方,必須要有一個集中管理的地方,那麼在spring cloud 中 這個功能由Eurka來完成,像阿里Dubbo裡的服務治理,用了ZoonKepper。但無論是spirng cloud 還是 dubbo,解決的東西是相同的。我打個比喻:動物園裡有老虎、獅子、狗熊等等,那麼這裡的動物園就是服務治理中心,老虎、獅子、狗熊就是各個獨立的微服務了。

推薦Eurka相關知識地址:http://geek.csdn.net/news/detail/130223

5、資源中心,集中管理js\css,將靜態資源統一管理,必須解決跨域問題。大型網站都有自己的靜態資源伺服器的,用nginx做靜態資源伺服器是一個很好的選擇,只是不便於開發,所以我們用一個boot工程來做這個事情,有利有弊。

6、spring-cloud-config配置集中化的實現,建立 confgBus 工程,各微服務通過configbus拉取配置資訊,實現配置集中管理。用一個git工程專門存放配置檔案,spring-cloud-config與git完美配合。

關於配置集中化,很多人在思考能否做到靜默修改配置檔案,也就是修改配置檔案不重啟服務就能生效,這是一個很有意義的問題。

7、spring-cloud-ribbon 負載均衡-RestTemplate。比如我有一個服務部署了2個節點,在服務治理中心是會有2個例項的,那麼服務呼叫方是呼叫那個例項呢,利用ribbon,底層是輪尋?ip Hash?最小連線數?可以去深究,但這個框架已經幫我們考慮好了,服務呼叫方只要通過服務治理縱向呼叫服務即可。

8、引入Redis、Memcached 快取技術實現分散式架構session共享、解決高併發業務。快取,本身就是常態技能,為了解決關係型資料庫效能問題,這類key-value型資料庫 響應快 效能高,spring-cloud對redis有不錯的封裝整合,使用起來很方便。

redis其對資料結構string list set hash等有很好的支援,還有就是RDB、AOF的支援等,優越於memcached。

9、引入RMQ,實現訊息佇列。類似於redis,spring-cloud對mq也有不錯的封裝整合,使用起來也很方便。什麼樣的場景要用訊息中介軟體,MQ也好,KafKa也好,都有訊息生產者與訊息消費者。一般使用在資料後置處理的場景,也就是說在大量資料資訊無法在瞬時處理時,可以將這些資料傳送到訊息件裡,再通過消費者快取消費的方式處理資料。為了響應快,我們在很多場景下用了Redis等快取,基於記憶體操作的redis解決了資料處理的快速性,而資料庫的持久化是快不得的,所以通過訊息快取,非同步持久化。

10、引入ZoonKepper、Kafka、ELK(elasticsearch、logstash、kibana)、MogoDB實現資料監控、日誌採集。

訊息佇列Kafka,基於主題topic形式,建立訊息監聽器。相較MQ而言,Kafka解決的點是大資料量的訊息。Kafka叢集由Zoonkepper來管理。而開源的ELK技術,對於大體量日誌有很好的支援,基於文件型ES資料庫,資料量級為PB,並且elk的核心解決的即時日誌儲存於搜尋。

11、引入oauth2.0,tocken機制,實現介面鑑權。對於介面的呼叫,可以限流,也就是設定一個固定大小的請求佇列,請求時判斷限流佇列是否已滿,已滿則提示等待,未滿則進隊,消費完則出隊。在有限資源的情況下,緩衝伺服器壓力。

12、spring-cloud-zuul實現閘道器appGateWay 。為什麼要用閘道器,這裡的場景是外部呼叫內部的介面,微服務介面是通過服務治理中心來治理的,所有消費者都是從治理中心去找例項,至於請求怎麼分配,這個事情spring cloud 的eurka已經為我們處理了。外部請求方通過閘道器先走服務治理中心這扇門,進去後才能找到對應的介面。

13、使用Docker、容器實現專案部署、多節點部署,使用CICD \Jekins實現專案自動化構建。小專案java -jar直接跑,不一定非得docker。docker可以擴容,在不同場景要求建立不同數量的容器例項,傳統方式自然是做不到的。

    關於spring cloud學習,推薦一個人:翟永超。我很多知識都是閱讀了他的《SpringCloud微服務實戰》,這本書對SpringCloud體系有較詳細的論述。翟永超目前好像任職於永輝,可以訪問他的主頁 http://blog.didispace.com/aboutme/。在微服務-spring cloud領域,個人認為他已經是先驅型人物。    目前國內的微服務架構即阿里的Dubbo,相比於Spring Cloud而言,Spring Cloud背後是Spring Source,社群活活躍度自然佔優。Dubbo主要是實現了服務治理及服務呼叫,對於微服務體系其他實現諸如配置集中化需要引入其他開源技術。而Spring Cloud 體系較為完善,對於想上手微服務的朋友們 建議從Spring Cloud入手。Dubbo服務治理必須用Zookeeper,如果你用了spring cloud再去用Dubbo,把dubbo從github下下來,用tomcat去跑dubbo專案,再啟動windows版的zookeeper。你會發現還是spring cloud +eurka比較乾淨,畢竟已經是封裝完美了。以下是Dubbo與Spring Cloud的架構體系對比:
蘇槐的文章“快速體驗微服務架構”,比較全面的展示了微服務架構的面貌,這裡做一個提煉,收藏並分享給大家。
       相對於“完美”的微服務架構方案,微服務架構簡單模式可以暫且不用關注保障資料一致性的分散式事務技術、方便程式包在環境間(開發、測試、生產)遷移的配置中心元件、監控 API 呼叫情況的呼叫鏈元件、避免系統超載的斷路器元件、方便 API 管理和測試的 API 文件框架、Zookeeper、Redis,以及各種 MQ。只需要關注常常談到的 註冊中心、服務發現、負載均衡 和 服務閘道器 即可。
使用微服務簡單模式進行開發的四個步驟:
1、沿用組織中現有的技術體系開發單一職責的微服務。
2、服務提供方將地址資訊註冊到註冊中心,呼叫方將服務地址從註冊中心拉下來。
3、通過門戶後端(服務閘道器)將微服務 API 暴露給門戶和移動 APP。
4、將管理端模組整合到統一的操作介面上。 
為了實現以上 4 點,相對應的就是下面必需掌握的基礎技術(必需的元件)。
註冊中心、服務發現、負載均衡:對應上邊第一步與第二步
服務閘道器:對應上邊第三步
管理端整合框架:對應上邊第四步
註冊中心、服務發現、負載均衡
      和單體架構不同,微服務架構是由一系列職責單一的細粒度服務構成的 分散式網狀結構,服務之間通過輕量機制進行通訊,這時候必然引入一個 服務註冊發現 問題,也就是說服務提供方要將自己的服務地址註冊到某個地方(服務註冊中心, Service Registry Center),服務的呼叫方可以從服務註冊中心找到需要呼叫的服務的地址(服務發現,Service Discovery)。同時,服務提供方一般以叢集方式提供服務,也就引入了 負載均衡 的需求。
根據負載均衡(Load Balancer,簡稱 LB)所在位置的不同,目前主要的服務註冊、發現和負載均衡方案有三種:
a、集中式 LB 方案
第一種是集中式 LB 方案,在服務消費者和服務提供者之間有一個獨立的 LB,LB 通常是專門的硬體裝置如 F5,或者基於軟體如 LVS,HAproxy 等實現。服務呼叫者呼叫服務時,向 LB 發起請求,LB 再根據一定的策略(比如輪詢、隨機、最小響應時間、最小併發數等等)將請求路由到指定的服務。這個方案的最大問題是:呼叫者和提供者之間增加了一跳,LB 也最有可能成為整個系統的瓶頸。
b、程序內 LB 方案
第二種是程序內 LB 方案,針對集中式 LB 的不足,程序內 LB 方案將 LB 的功能以庫的形式整合到服務消費方程序裡頭,該方案也被稱為軟負載 (Soft Load Balancing) 或者客戶端負載方案。
 其原理是:服務提供者將自身的地址傳送到服務註冊中心,同時定時傳送心跳給註冊中心,註冊中心按心跳情況判斷是否將此節點從登錄檔中摘除。服務提供者呼叫服務時,先從註冊中心拉取服務註冊資訊,然後根據一定的策略去呼叫服務節點。
 這種情況下,即使註冊中心宕機,呼叫方也可以根據記憶體中已經拉到的服務地址將請求路由到正確的服務上去。這個方案的最大問題是:服務呼叫者可能需要整合註冊中心的客戶端,即將來註冊中心服務端升級,可能會需要升級註冊中心客戶端。
c、主機獨立 LB 程序方案
 第三種是主機獨立 LB 程序方案,該方案是針對第二種方案的不足而提出的一種折中方案,原理和第二種方案基本類似,不同之處是,他將 LB 和服務發現功能從程序內移出來,變成主機上的一個獨立程序,主機上的一個或者多個服務要訪問目標服務時,他們都通過同一主機上的獨立 LB 程序做服務發現和負載均衡。該方案的典型案例是 Airbnb 的 SmartStack 服務發現框架。這個方案的最大問題是:部署和運維比較麻煩。
 當下,隨著 Netflix 的微服務方案和 Spring Cloud 的興起與成熟,第二個方案 成為我們的首選。我們推薦使用 Eureka 做服務註冊中心,Ribbon 做客戶端服務發現和負載均衡。
 這個選擇的最大好處是 簡單 + 實用 + 可控,不用引入額外的 Zookeeper、Etcd 做註冊中心,部署和運維也都比較簡單。從程式碼上來說,使用起來也非常簡單。
 只是,需要注意的是,這種方案一般是用來做 區域網內 的負載均衡,如果要為開放到網際網路的服務做負載均衡,可以使用 Nginx Upstream 來做。
 下面是 Eureka 最重要的幾個引數配置,從這些引數也可以大概看看 Eureka 是如何工作的。
由於 Eureka 的註冊及過期機制,服務從啟動到完全可用需要近 2 分鐘的時間,所以,為了提高開發及測試環境中的發版速度,我們改了以下幾個引數。生產時,一定要改回去。
Eureka 註冊中心的介面如下:
詳細資訊可參考https://github.com/Netflix/eureka和https://github.com/Netflix/ribbon。
 服務閘道器
 通常,一個大系統裡會有很多職責單一的微服務,如果門戶系統或移動 APP 來呼叫這些微服務的 API 時,至少要做好兩件事:
由統一的入口來呼叫微服務的 API
API 鑑權
 這就需要一個 服務閘道器。2015 年,我們使用 Rest Template + Ribbon 做了一個簡單的 API 閘道器。原理就是當 API 閘道器接到請求 /service1/api1.do 時,將請求轉發到 service1 對應的微服務的 api1 介面。
 後來,發現我們實現的功能,Spring Cloud Zuul 都有比較好的實現,也就切換到 Zuul 上面去了。Zuul 是 Netflix 基於 Java 開發的服務端 API 閘道器和負載均衡器。
 除此之外,Zuul 還可以對過濾器進行動態的載入、編譯、執行。最令人吃驚的是,Zuul 的轉發效能據說和 Nginx 差不多。詳細資訊可參考https://github.com/Netflix/zuul。
總的來說,一般情況下,API 閘道器(可以稱為門戶後端)用來進行反向代理、許可權認證、資料剪裁、資料聚合等。
 管理端整合框架
 掌握註冊中心、服務發現、負載均衡和服務閘道器技術後,微服務已經可以為門戶系統和移動 APP 提供可靠服務。但是,給後臺運營人員使用的管理端是怎麼實現的呢?
由於後端運營系統的壓力不大,我們可以通過 CAS 和 UPMS(UPMS 是我們團隊研發的契合微服務架構的使用者及許可權管理系統,我們將分享到青柳雲官網,歡迎關注)將單獨開發的微服務整合起來。
三步整合一個微服務的基本過程就是:
 在微服務中引入基於 Spring Boot 的 security starter,starter 裡包含了系統的頂端 Banner 和左側選單。
將微服務的訪問地址註冊到 UPMS 中,這個地址作為此微服務的入口選單(一級選單)。
 在 UPMS 中配置微服務的功能選單及角色許可權資訊。使用者從瀏覽器開啟一個微服務的時候,security starter 會呼叫 UPMS 的 API 拉取所有的微服務清單(一級選單)和當前微服務的功能清單(二級選單),並將當前微服務的頁面在內容區展現給使用者。
應用架構圖:
 UPMS 截圖,橙色部分由 UPMS 框架提供,紅色框為微服務的頁面:
 UPMS 通過“模組”功能接入新的微服務:
所以,到最後,一個簡單模式的基於微服務架構的系統就可以長成這樣:
至此,基本的微服務架構已經搭建起來。下面來聊聊怎麼解決微服務運維的問題。
      微服務架構的運維問題,主要是相對於單體架構來說的。因為實施微服務架構後,整個系統的模組一下子比原來多了很多,模組變多後,部署和維護的工作量都會變大。所以,解決運維難的問題,可以先從 自動化 的角度來解決。
 更進一步,如果希望更好地發揮微服務架構的優勢,規避缺點,則建議準備一個可靠的基礎設施,包含自動構建、自動部署、日誌中心、健康檢查、效能監控等功能。
否則,很有可能會因為微服務架構的缺點導致我們的團隊喪失對微服務架構的信心,從而回到單體架構的老路上去。工欲善其事,必先利其器,這一點真的很重要。
 持續整合
 單體應用被微服務化後,很有可能從原來的一個程式包分成了 10 個、20 個甚至更多的程式包。那麼,我們首先遇到的麻煩就是部署工作直接擴大了 10 - 20 倍。這時,持續整合的方法和工具就成了實施微服務架構的前提條件。我們在實踐過程中,利用基於 Docker 的容器服務平臺自動部署整個系統的微服務。其過程如下圖:
如果沒有微服務支撐平臺,也可以通過 Shell 指令碼的形式來呼叫 Jenkins API 和 Docker API。
主要過程是:
 呼叫 Jenkins 命令從程式碼倉庫拉取程式碼,並打包程式碼。
 呼叫 Docker /build 和 /images/push 命令構建映象,並將映象推送到私有映象倉庫中。
 呼叫 Docker /containers/create 和 /containers/start 命令建立並啟動容器。
 配置中心
 在開發 / 測試環境上,程式包已經被打包成 Docker 映象,如果能將通過測試的映象直接推到生產環境,可以直接省去為生產環境而重複進行的打包部署工作,豈不是很美?
如果需要達到這個效果,就需要將程式包打包成具有環境無關性,也就是說,在程式包裡是不可以有環境相關的配置資訊的,這也就引入了 配置中心 元件。
 這個元件非常簡單,只是根據專案代號、環境代號和微服務代號來獲取微服務所需要的鍵值對。例如:
ProjectA_PRODUCTION_MicroService1_jdbc.connection.url。
 使用配置中心還有一個很重要的附加價值,那就是可以做到不同環境的配置資訊可以由不同的人來管理,加強了生產環境的配置資訊的安全性,例如資料庫帳號和密碼。
 這個模組也有一些開源的專案可以參考,例如百度 disconf,Spring Cloud Config。而我們自己發楊了重複造輪子的精神,開發了一個配置中心微服務,以方便地與上面提到的 UPMS 進行整合。
注意:這一元件並不是微服務架構簡單模式的必需元件,只是建議使用。
 監控告警
 單體應用被微服務化後,一個單體應用被拆成了很多個微服務,系統的健康巡檢、效能監控、業務指標健康、檔案備份監控、資料庫備份監控、定時任務執行情況監控都變得困難。
所以,為了讓運維的同學能生活得踏實點,最好也能把監控平臺給建了。如果希望快速搭建監控平臺,可以考慮 Nagios,Zabbix。如果希望擴充套件性、可定製性更好,可以考慮使用以下元件搭建:
Collectd 是一款主機、資料庫、網路、儲存指標採集器。GitHub 上 1653 個 Star。
 Metrics 是一款牛逼的 JVM 指標採集器,提供了很多模組可以為第三方庫或者應用提供輔助統計資訊, 比如 Jetty, Logback,Log4j,Apache HttpClient,Ehcache,JDBI,Jersey,它還可以將度量資料傳送給 Ganglia 和 Graphite 以提供圖形化的監控。GitHub 上 5000+ 個 Star。
CAdvisor 是一款 Docker 容器指標採集器,Google 出品。GitHub 上 6000 個 Star。
Grafana 是一款非常精美的開源儀表盤工具,支援 Graphite,InfluxDB ,MySQL 和 OpenTSDB 等多種資料來源。GitHub 上 17000 個 Star。
 InfluxDB 是一款優秀的開源分散式時序資料庫,目前在時序資料中排名第一,它的特性中,RETENTION POLICY 可以自動地清除不需要的歷史資料,很實用。GitHub 上 11175 個 Star。
除了以上模組,我們還開發了一個模組,用來探測應用程式的健康情況和效能,在主機、程式健康情況、程式效能等各種指標出現異常時,傳送警報給運維人員。
 在這篇文章結束的時候,我們可以回過頭來看看,我們只需要在開發層面理解了註冊中心、服務發現、負載均衡、服務閘道器和管理端整合框架,在運維層面準備好持續整合工具、配置中心和監控告警工具,就可以很容易地落地微服務架構,享受微服務架構帶來的精彩。
 Eureka是Netflix開發的服務發現元件,本身是一個基於REST的服務。Spring Cloud將它整合在其子專案spring-cloud-netflix中,以實現Spring Cloud的服務發現功能。

15、使用Nginx實現反向代理。