序 1
16年國慶假期之后,我所在的公司因為業務需要,想搭建一個 API網關來綜合治理已有業務調用服務(我司之前采用的是當當的 Dubbo擴展框架 Dubbox)。前期,我和同事們在技術選型環節,討論了諸多目前比較紅火的技術框架和工具。最后達成一致,采用微服務,來重構和調整原先這些 Dubbox服務,并決定使用 Spring Cloud(以下簡稱 sc)來實現 API網關,爭取在 17年能順利平滑地從 Dubbox過度到 sc。而具體的 API網關 demo研發工作就落實到我這里。
在開始研發工作之前,我參閱了包括官網在內很多 sc研發資料,也去全球最大的同性技術交友網站 GitHub上找了很多代碼來仔細研讀。但感覺老外的這些 Guide(指南)總是講的不是很通透。也許是有些概念他們覺得太基礎了,就直接略過不表。因此我也感到很迷茫,老是問自己,到底應該如何去實現這個 API網關,完成公司指派給我的研發任務呢?
幸好,某一天我看到《 SpringCloud與 Docker實戰微服務》這本開源書。根據書中例子,我幾乎沒有費什么大工夫就搭建了一個 API網關的 demo。甚至其中某些講解點,看了之后能讓我一下子恍然大悟,回頭再看那些老外的 Guide,我終于明白了其中的“奧義”。我真的非常感激這位開源書作者,他深入淺出地將 sc所涉及的各種知識點和工具的使用做了完整和詳細的敘述。從此,我也記住了此書作者的網名 itmuch。
幾天后,我將 demo做了細化和擴展,并在 oschina的碼云網站上開源分享了出去(具體網址見 http://git.oschina.net/darkranger/spring-cloud-books )。而無巧不巧, itmuch居然在我項目下的評論區留言了。經過加 QQ,加微信一系列同性技術交友過程(你們懂的)取得了聯系,也終于知道了這位 itmuch的真名,那就是此書作者周立同學。在閑聊過程中,他透露了自己正在以那本《 Spring Cloud與 Docker實戰微服務》開源書為基礎,繼續擴展和具體深入 sc這套微服務開發體系所包含的所有技術點,準備出版成冊,讓更多的朋友和企業能學習和借鑒 sc這套東西開發符合自己業務場景的微服務框架。并邀請我為新書做校對和修正工作。正巧,我也越來越喜歡鉆研 sc,也希望對自己碰到的一些問題向他指教,所以就答應了下來。這其中的過程真的一言難敘,總算最后我也不辱使命地完成了這本書的校對工作。
我可以很負責的說,本書是周立同學本人在工作和學習 sc后總結出的精華,書中每段代碼,每個字都是他自己寫的,絕無任何抄襲之舉。完全可以說是一個努力勤奮、能獨立思考、認真做事的同學的良心之作。這樣的“業界良心”在如今這個充滿浮躁的社會中已不多見。希望有更多的讀者能珍惜此書,感謝周立同學給我們的幫助。除此之外,我也希望讀者能在閱讀完此書后,可以自己寫點代碼,親身去實踐一把,感受 sc的精妙之處。
最后,在草促完成本文之前,值此新春佳節之際,我也祝大家新年快樂,家庭安康,財源滾滾,愛情事業雙豐收。
2017年 1月 25日
農歷丙申年臘月二十八
吳峻申 青客機器人有限公司架構師
序 2
2013年,我在 EMC聽了一個關于 Docker與測試的分享,才第一次近距離認識 Docker。在 2014年底時,在項目上開始接觸 Docker。2015年上半年,我讀了兩本書: ThePhoenix Project和 Migrating to Cloud-NativeApplicationArchitectures。這兩本書讓我對 DevOps、微服務和云原生架構有了初步的認識。
2015年 9月,我以首席架構師的身份加入麻袋理財,當時第一件事情就是就借助 Dao-Cloud在公司內部推行基于 Docker的基礎落地的方案。花了三個月,一個簡易的方案就已經可以正常運作。但是在這個過程中,卻發現和應用的契合度不是太高,需要對應用的架構做改造。
2016年年初當時正好有一個項目要做 2.0,之前是一個典型的單體應用(使用 Spring MVC),這次準備做微服務改造,以滿足業務對技術快速迭代、橫向擴展的要求。我當時對 Spring Boot和 Spring Cloud已經有所耳聞,但是還停留于 Demo的地步。正好借著這個機會,準備推廣 Spring Boot。之后有個全新的項目,我們完全按照微服務架構,使用 Spring Boot和 Cloud進行開發,并采用 CI/ CD自動化流程和容器化部署。
2016年 10月份時,一次偶然的計劃, Spring Cloud中國社區的許進找到了我,讓我把團隊在實踐過程中的經驗總結在社區做了分享,從而認識了本書的作者周立。當時周立正好在寫一本書,他希望我能夠幫他進行 review,我就欣然答應了。
看到了書的標題《 Spring Cloud與 Docker微服務實戰》,這不就是我一直在做的工作嗎?于是我連夜把這本書讀了一遍,感覺相見恨晚,如果一年前有這本書,那我就可以少走很多彎路了。
本書用一個例子貫穿始終,講解了 SpringCloud的經典組件、微服務架構,以及與 Docker的集成。書中提供了詳細的代碼,可以讓讀者在了解基礎概念的同時,可以馬上腳踏實地的擼起袖子寫代碼。
王天青 DaoCloud首席架構師
2017年 3月
序 3
最近幾年,微服務的概念非常火爆,由于它確實能解決傳統單體應用所帶來的種種問題
(比如代碼可維護性低、部署不靈活、不夠穩定、不易擴展,等等),所以大家對“如何成功實施微服務架構”越來越感興趣。在 Java技術棧中,SpringCloud獨樹一幟,提供了一整套微服務解決方案,它基于 SpringBoot而構建,延續了 Spring體系一貫的“簡單可依賴”,但是由于微服務本身涉及到的技術或概念比較廣,所以在正式“入坑”之前,最好能有一本實戰性強的書籍作為參考。但是很遺憾, SpringCloud太新了,國內幾乎沒有一本完整講解其用法的新書。在今年年初,我偶然得知周立兄在編寫 SpringCloud相關的書籍,感到非常驚喜,在和他交流的過程中,我能感覺到他對技術的把控力以及對知識分享的熱情!閱讀這本書的過程是非常愉悅的,不僅僅是因為它結構之清晰,文風之流暢,更重要的是實戰型極強,相信大家能在本書的指導下,順利地基于 SpringCloud&Docker打造出自己的微服務應用。
杜云飛 上海小蟲數據
序 4
隨著微服務在國內的推廣普及,許多企業紛紛將微服務作為 IT架構的轉型方向,并進行大量探索和嘗試,但在具體落地實踐微服務的過程中還缺乏實際的設計思路和實現方案。本書從微服務設計原則和理念出發,詳細說明了如何通過 SpringCloud及 Docker建立高效可用的微服務解決方案,并對 Spring Cloud的架構及組件、容器鏡像的制作與編排進行逐一講解,具備較強的實戰指導意義。本書能夠幫助技術人員快速了解和應用微服務,通過技術的變革與提升幫助業務適應市場的快速變化,從而提升技術的價值。
廖俊杰,廣發銀行 IDC團隊負責人
序 5
隨著微服務架構提出和廣泛流行, Spring Cloud提供了一套完整的微服務解決方案。目前國內已經有眾多公司生產大規模地 Spring Cloud解決 IT架構、提高生產力。相信在 1-3年內, Spring Cloud無疑是 Java企業級微服務應用之中的霸主。在《 Spring Cloud與 Docker微服務架構實戰》一書中,作者由淺入深的對 Spring Cloud的主要常用組件進行案例剖析和精彩講解,讓讀者能快速上手,快速搭建基于 Spring Cloud的微服務應用。
許進(xujin.org)Spring Cloud中國社區創始人,中間件高級研發工程師
序 6
周立在寫完本書初稿后,我第一時間拿到了初稿,從零學習了 SpringCloud,SpringCloud提供了構建分布式系統所需的“全家桶”。如果你想從零搭建一套分布式系統,本書可以作為你的領路者,帶你進入 spring cloud的世界。
張開濤
序 7
在 Spring尚未出現的“蠻荒”時代, Java程序員們還在迷茫地創造著各種“語法糖”來試圖提高生產效率。然而無論怎么努力, Java語言仍被許多人冠以“裹腳布”的名號——畢竟你一不小心就會把它寫的又臭又長。
隨著 Spring體系的出現與逐步完善,似乎有一種經歷著 Java工業革命的感覺。的確,任何事物都各有利弊,但我仍然想說, Spring團隊給 Java程序員們帶來了春天(就像它的名字一樣),它神奇地把“裹腳布”變成了“絲綢”,因為它最大的特質可以用兩個字來形容——優雅。相信使用過 SpringFramework、SpringMVC、SpringData、SpringBoot或 Spring Cloud等一系列框架,并研讀過它們源代碼的人,都能夠體會到“優雅”二字的含義。
盡管 Spring家族擁有如此多而美好的大塊“語法糖”,但它們過去在國內的傳播似乎都不怎么順利。我經常說,國內對新技術的廣泛應用一般比國外要晚三到五年,無論后端、前端還是架構理念。這是許多因素導致的,比如信息閉塞、語言不通、甚至固步自封。我相信隨著國內互聯網人才越來越多,新技術應用的延時一定會越來越短。或許很多人為了舊系統的穩定而不愿升級,這可以理解,但我希望人們可以擁抱新的事物,而不是排斥。現如今微服務架構理念興起,人們急需一個快捷、穩定、一站式的分布式微服務解決方案, Spring Cloud正是為此而誕生。可國內熟知 Spring Cloud的人目前仍寥寥無幾,大部分人從未聽說過,想要學習的人不知從何開始,對官方的英文文檔也一知半解。人們需要一本能把他們領進 Spring Cloud這扇門的“紅寶書”,這便是本書的目的,也是本書作者周立的初衷——希望能夠為減少國內新技術的延時而出一份力。
我與周立在 2016年相識,在短暫的交流后我們都產生了相見恨晚的感覺。遇見志同道合的人并不容易,我們的技術理念很相似。他有著對技術的熱忱、靈活的頭腦、以及開源分享技術的無私精神,正是這股精神促使他做了許多分享技術的事情,并且編寫了這本書(相信我,寫書并不賺錢)。我十分欣賞周立身上的這些特質,因此當他跟我提到想出書并找我幫忙時,我毫不猶豫地答應了他。我相信他未來能夠成為某一技術領域的專家,這是他的目標,他也具備這樣的潛質。
本書的切入點也非常好,它并不糾結于冗長的源碼解讀或原理解釋,而是更多地注重實戰,這在如今互聯網爆炸式發展的時代相當重要。現在人們更傾向于使用敏捷開發盡快做出產品來進行試錯,并在后續版本中快速迭代。因此本書的實戰經驗在軟件工程層面上會給予閱讀者很大提升,它可以讓你更快地搭建分布式微服務架構,然后把精力留在編寫業務邏輯上,提高你的生產力,并最終做出更好的產品——這也是 Spring團隊一直希望達到的效果。
現在,讓我們隨本書進入 Spring Cloud的世界,一起感受它的優雅吧!
張英磊
2017年 3月 29日
1 微服務架構概述. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1 單體應用架構存在的問題1
1.2 如何解決單體應用架構存在的問題3
1.3 什么是微服務3
1.4 微服務架構的優點與挑戰5
1.4.1 微服務架構的優點5
1.4.2 微服務架構面臨的挑戰5
1.5 微服務設計原則6
1.6 如何實現微服務架構7
1.6.1 技術選型7
1.6.2 架構圖及常用組件8
2 微服務開發框架——Spring Cloud . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.1 Spring Cloud 簡介10
2.2 Spring Cloud 特點10
2.3 Spring Cloud 版本11
2.3.1 版本簡介11
2.3.2 子項目一覽12
2.3.3 Spring Cloud/Spring Boot 版本兼容性13
3 開始使用Spring Cloud 實戰微服務. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.1 Spring Cloud 實戰前提14
3.1.1 技術儲備14
3.1.2 工具及軟件版本15
3.2 服務提供者與服務消費者16
3.3 編寫服務提供者16
3.3.1 手動編寫項目17
3.3.2 使用Spring Initializr 快速創建Spring Boot 項目21
3.4 編寫服務消費者23
3.5 為項目整合Spring Boot Actuator 25
3.6 硬編碼有哪些問題27
4 微服務注冊與發現. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.1 服務發現簡介29
4.2 Eureka 簡介31
4.3 Eureka 原理31
4.4 編寫Eureka Server 33
4.5 將微服務注冊到Eureka Server 上35
4.6 Eureka Server 的高可用36
4.6.1 將應用注冊到Eureka Server 集群上38
4.7 為Eureka Server 添加用戶認證39
4.7.1 將微服務注冊到需認證的Eureka Server 40
4.8 理解Eureka 的元數據41
4.8.1 改造用戶微服務41
4.8.2 改造電影微服務41
4.9 Eureka Server 的REST 端點43
4.9.1 示例45
4.9.2 注銷微服務實例49
4.10 Eureka 的自我保護模式51
4.11 多網卡環境下的IP 選擇52
4.11.1 忽略指定名稱的網卡52
4.11.2 使用正則表達式,指定使用的網絡地址52
4.11.3 只使用站點本地地址53
4.11.4 手動指定IP 地址53
4.12 Eureka 的健康檢查53
5 使用Ribbon 實現客戶端側負載均衡. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
5.1 Ribbon 簡介56
5.2 為服務消費者整合Ribbon 57
5.3 使用Java 代碼自定義Ribbon 配置60
5.4 使用屬性自定義Ribbon 配置63
5.5 脫離Eureka 使用Ribbon 64
6 使用Feign 實現聲明式REST 調用. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
6.1 Feign 簡介67
6.2 為服務消費者整合Feign 67
6.3 自定義Feign 配置69
6.4 手動創建Feign 72
6.4.1 修改用戶微服務72
6.4.2 修改電影微服務76
6.5 Feign 對繼承的支持78
6.6 Feign 對壓縮的支持79
6.7 Feign 的日志80
6.8 使用Feign 構造多參數請求82
6.8.1 GET 請求多參數的URL 82
6.8.2 POST 請求包含多個參數83
7 使用Hystrix 實現微服務的容錯處理. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
7.1 實現容錯的手段85
7.1.1 雪崩效應85
7.1.2 如何容錯86
7.2 使用Hystrix 實現容錯88
7.2.1 Hystrix 簡介88
7.2.2 通用方式整合Hystrix 89
7.2.3 Hystrix 斷路器的狀態監控與深入理解91
7.2.4 Hystrix 線程隔離策略與傳播上下文93
7.2.5 Feign 使用Hystrix 96
7.3 Hystrix 的監控101
7.3.1 Feign 項目的Hystrix 監控102
7.4 使用Hystrix Dashboard 可視化監控數據103
7.5 使用Turbine 聚合監控數據105
7.5.1 Turbine 簡介105
7.5.2 使用Turbine 監控多個微服務105
7.5.3 使用消息中間件收集數據108
8 使用Zuul 構建微服務網關. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
8.1 為什么要使用微服務網關113
8.2 Zuul 簡介115
8.3 編寫Zuul 微服務網關115
8.4 Zuul 的路由端點118
8.5 Zuul 的路由配置詳解119
8.6 Zuul 的安全與Header 122
8.6.1 敏感Header 的設置122
8.6.2 忽略Header 123
8.7 使用Zuul 上傳文件124
8.7.1 編寫文件上傳微服務124
8.8 Zuul 的過濾器127
8.8.1 過濾器類型與請求生命周期127
8.8.2 編寫Zuul 過濾器128
8.8.3 禁用Zuul 過濾器130
8.9 Zuul 的容錯與回退130
8.9.1 為Zuul 添加回退131
8.10 Zuul 的高可用133
8.10.1 Zuul 客戶端也注冊到了Eureka Server 上133
8.10.2 Zuul 客戶端未注冊到Eureka Server 上133
8.11 使用Sidecar 整合非JVM 微服務134
8.11.1 編寫Node.js 微服務135
8.11.2 編寫Sidecar 136
8.11.3 Sidecar 的端點138
8.11.4 Sidecar 與Node.js 微服務分離部署139
8.11.5 Sidecar 原理分析139
9 使用Spring Cloud Config 統一管理微服務配置. . . . . . . . . . . . . . . . . . . . . . . 142
9.1 為什么要統一管理微服務配置142
9.2 Spring Cloud Config 簡介143
9.3 編寫Config Server 144
9.3.1 Config Server 的端點145
9.4 編寫Config Client 147
9.5 Config Server 的Git 倉庫配置詳解149
9.6 Config Server 的健康狀況指示器152
9.7 配置內容的加解密153
9.7.1 安裝JCE 153
9.7.2 Config Server 的加解密端點153
9.7.3 對稱加密153
9.7.4 存儲加密的內容154
9.7.5 非對稱加密155
9.8 使用/refresh 端點手動刷新配置155
9.9 使用Spring Cloud Bus 自動刷新配置157
9.9.1 Spring Cloud Bus 簡介157
9.9.2 實現自動刷新158
9.9.3 局部刷新159
9.9.4 架構改進159
9.9.5 跟蹤總線事件160
9.10 Spring Cloud Config 與Eureka 配合使用161
9.11 Spring Cloud Config 的用戶認證162
9.11.1 Config Client 連接需用戶認證的Config Server 163
9.12 Config Server 的高可用164
9.12.1 Git 倉庫的高可用164
9.12.2 RabbitMQ 的高可用164
9.12.3 Config Server 自身的高可用165
10 使用Spring Cloud Sleuth 實現微服務跟蹤. . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
10.1 為什么要實現微服務跟蹤167
10.2 Spring Cloud Sleuth 簡介168
10.3 整合Spring Cloud Sleuth 170
10.4 Spring Cloud Sleuth 與ELK 配合使用172
10.5 Spring Cloud Sleuth 與Zipkin 配合使用176
10.5.1 Zipkin 簡介176
10.5.2 編寫Zipkin Server 176
10.5.3 微服務整合Zipkin 178
10.5.4 使用消息中間件收集數據181
10.5.5 存儲跟蹤數據183
11 Spring Cloud 常見問題與總結. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
11.1 Eureka 常見問題186
11.1.1 Eureka 注冊服務慢186
11.1.2 已停止的微服務節點注銷慢或不注銷187
11.1.3 如何自定義微服務的Instance ID 188
11.1.4 Eureka 的UNKNOWN 問題總結與解決189
11.2 Hystrix/Feign 整合Hystrix 后首次請求失敗190
11.2.1 原因分析191
11.2.2 解決方案191
11.3 Turbine 聚合的數據不完整191
11.3.1 解決方案192
11.4 Spring Cloud 各組件配置屬性193
11.4.1 Spring Cloud 的配置193
11.4.2 原生配置193
11.5 Spring Cloud 定位問題思路總結194
12 Docker 入門. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
12.1 Docker 簡介197
12.2 Docker 的架構197
12.3 安裝Docker 199
12.3.1 系統要求199
12.3.2 移除非官方軟件包199
12.3.3 設置Yum 源199
12.3.4 安裝Dokcer 200
12.3.5 卸載Docker 201
12.4 配置鏡像加速器201
12.5 Docker 常用命令202
12.5.1 Docker 鏡像常用命令202
12.5.2 Docker 容器常用命令204
13 將微服務運行在Docker 上. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
13.1 使用Dockerfile 構建Docker 鏡像209
13.1.1 Dockerfile 常用指令210
13.1.2 使用Dockerfile 構建鏡像215
13.2 使用Docker Registry 管理Docker 鏡像217
13.2.1 使用Docker Hub 管理鏡像217
13.2.2 使用私有倉庫管理鏡像219
13.3 使用Maven 插件構建Docker 鏡像220
13.3.1 快速入門221
13.3.2 插件讀取Dockerfile 進行構建222
13.3.3 將插件綁定在某個phase 執行223
13.3.4 推送鏡像224
13.4 常見問題與總結226
14 使用Docker Compose 編排微服務. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
14.1 Docker Compose 簡介227
14.2 安裝Docker Compose 227
14.2.1 安裝Compose 228
14.2.2 安裝Compose 命令補全工具228
14.3 Docker Compose 快速入門229
14.3.1 基本步驟229
14.3.2 入門示例229
14.3.3 工程、服務、容器230
14.4 docker-compose.yml 常用命令230
14.4.1 build 230
14.4.2 command 231
14.4.3 dns 231
14.4.4 dns_search 231
14.4.5 environment 231
14.4.6 env_file 232
14.4.7 expose 232
14.4.8 external_links 232
14.4.9 image 232
14.4.10 links 232
14.4.11 networks 233
14.4.12 network_mode 233
14.4.13 ports 233
14.4.14 volumes 233
14.4.15 volumes_from 234
14.5 docker-compose 常用命令234
14.5.1 build 234
14.5.2 help 235
14.5.3 kill 235
14.5.4 logs 235
14.5.5 port 235
14.5.6 ps 235
14.5.7 pull 235
14.5.8 rm 236
14.5.9 run 236
14.5.10 scale 236
14.5.11 start 236
14.5.12 stop 236
14.5.13 up 236
14.6 Docker Compose 網絡設置237
14.6.1 基本概念237
14.6.2 更新容器237
14.6.3 links 238
14.6.4 指定自定義網絡238
14.6.5 配置默認網絡239
14.6.6 使用已存在的網絡239
14.7 綜合實戰:使用Docker Comose 編排Spring Cloud 微服務240
14.7.1 編排Spring Cloud 微服務240
14.7.2 編排高可用的Eureka Server 243
14.7.3 編排高可用Spring Cloud 微服務集群及動態伸縮245
14.8 常見問題與總結247
后記. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248