只有光頭才能變強
認識個人朋友可能都知道我這陣子去實習啦,去的公司說是用SpringCloud(但我以爲使用的力度並不大啊~~)...html
因此,這篇主要來說講SpringCloud的一些基礎的知識。(我就是現學現賣了,主要當作我學習SpringCloud的筆記吧!)固然了,個人水平是有限的,可能會有一些理解錯的的概念/知識點,還請你們不吝在評論區指正啊~~前端
SpringCloud GitHub Demo(看完文章的同窗能夠本身練手玩玩):java
項目結構圖:nginx
像我這種技術小白,看到這些詞(集羣/分佈式/微服務/SOA
)的時候,感受就是高不可攀的(高大尚的技術!!)。就好像剛學Java面向對象的時候,在論壇上翻閱資料的時候,無心看到"面向切面編程",也認爲這是高不可攀的(高大尚的技術!!)。git
但真正接觸到"面向切面編程"的時候,發現原來就是如此啊,也沒什麼大不了的。只不過當時被它的名字給唬住了...程序員
不知道各位在剛接觸這些名字集羣/分佈式/微服務/SOA
的時候,有沒有被唬住了呢??github
如下內容來源維基百科:算法
計算機集羣簡稱集羣是一種計算機系統,它經過一組鬆散集成的計算機軟件和/或硬件鏈接起來高度緊密地協做完成計算工做。在某種意義上,他們能夠被看做是一臺計算機。集羣系統中的單個計算機一般稱爲節點,一般經過局域網鏈接,但也有其它的可能鏈接方式。集羣計算機一般用來改進單個計算機的計算速度和/或可靠性。通常狀況下集羣計算機比單個計算機,好比工做站或超級計算機性能價格比要高得多
集羣技術特色:spring
在維基百科上說得也挺明白的了,我來舉個例子吧。編程
小周在公司寫Java程序,但公司業務在發展,一個Java開發者可能忙不過來,小周有的時候也得請個假呀。因而請了3y過去一塊兒作Java開發。平時小周和3y就寫Java程序,但3y可能有事要回學校一趟。沒事,公司還有小周作Java開發呢,公司開發還能繼續運做。
我寫了一個910便利網發佈到服務器去了,如今愈來愈多的人訪問了,訪問有點慢,怎麼辦???很簡單,(只有充錢才能變強),加配置吧(加cpu,加內存)。升級完配置以後,訪問人數愈來愈多,因而發現又不由用啦,在這臺機器上加配置已經解決不了了,怎麼辦???很簡單,(只有充錢才能變強),我再買一臺服務器,將910便利網也發佈到新買的這臺服務器上去。
特色:
好處:
集羣:同一個業務,部署在多個服務器上(不一樣的服務器運行一樣的代碼,幹同一件事)
如下內容來源維基百科:
分佈式系統是一組計算機,經過網絡相互鏈接傳遞消息與通訊後並協調它們的行爲而造成的系統。 組件之間彼此進行交互以實現一個共同的目標。
我也來舉個例子來講明一下吧:
如今公司有小周和3y一塊兒作Java開發,作Java開發通常jQuery,AJAX都能寫一點,因此這些活都由咱們來幹。但是呢,3y對前端不是很熟,有的時候調試半天都調不出來。老闆認爲3y是真的菜!因而讓小周專門來處理前端的事情。這樣3y就高興了,能夠專心寫本身的Java,前端就專門交由小周負責了。因而,小周和3y就變成了協做開發。
個人910便利網已經部署到兩臺服務器去了,可是愈來愈多的人去訪問。如今也逐漸承受不住啦。那如今怎麼辦啊??那繼續充錢變強??做爲一個理智的我,確定得想一想是哪裏有問題。如今910便利網的模塊有好幾個,全都丟在同一個Tomcat裏邊。
其實有些模塊的訪問是很低的(好比後臺管理),那我可不能夠這樣作:將每一個模塊抽取獨立出來,訪問量大的模塊用好的服務器裝着,沒啥人訪問的模塊用差的服務器裝着。這樣的好處是:1、資源合理利用了(沒人訪問的模塊用性能差的服務器,訪問量大的模塊單獨提高性能就行了)。2、耦合度下降了:每一個模塊獨立出來,各幹各的事(專業的人作專業的事),便於擴展
特色:
好處:
分佈式:一個業務分拆多個子業務,部署在不一樣的服務器上(不一樣的服務器,運行不一樣的代碼,爲了同一個目的)
集羣和分佈式並不衝突,能夠有分佈式集羣
如今3y的公司規模變大了,有5個小夥子寫Java,4個小夥子寫前端,2個小夥子作測試,1個小夥子作DBA。
其實我認爲分佈式/微服務/SOA這三個概念是差很少的,瞭解了其中的一個,而後將本身的理解往上面套就行了。不必細分每一個的具體概念~~(固然了,我很期待有大佬能夠在評論區留言說下本身的見解哈)
參考資料:
從上面所講的分佈式概念咱們已經知道,分佈式簡單理解就是:一個業務分拆多個子業務,部署在不一樣的服務器上
若是你接觸過一些分佈式的基礎概念,那確定會聽過CAP這個理論。就好比說:你學了MySQL的InnoDB存儲引擎相關知識,你確定聽過ACID!
首先,咱們來看一下CAP分別表明的是什麼意思:
C:數據一致性(consistency)
A:可用性(availability)
P:分區容錯性(partition-tolerance)
下面有三個節點(它們是集羣的),此時三個節點都可以相互通訊:
因爲咱們的系統是分佈式的,節點之間的通訊是經過網絡來進行的。只要是分佈式系統,那頗有可能會出現一種狀況:由於一些故障,使得有些節點之間不連通了,整個網絡就分紅了幾塊區域。
如今出現了網絡分區後,此時有一個請求過來了,想要註冊一個帳戶。
此時咱們節點一和節點三是不可通訊的,這就有了抉擇:
若是容許當前用戶註冊一個帳戶,此時註冊的記錄數據只會在節點一和節點二或者節點二和節點三同步,由於節點一和節點三的記錄不能同步的。
若是不容許當前用戶註冊一個帳戶(就是要等到節點一和節點三恢復通訊)。節點一和節點三一旦恢復通訊,咱們就能夠保證節點擁有的數據是最新版本。
通常咱們說的分佈式系統,P:分區容錯性(partition-tolerance)這個是必需的,這是客觀存在的。
CAP是沒法徹底兼顧的,從上面的例子也能夠看出,咱們能夠選AP,也能夠選CP。可是,要注意的是:不是說選了AP,C就徹底拋棄了。不是說選了CP,A就徹底拋棄了!
在CAP理論中,C所表示的一致性是強一致性(每一個節點的數據都是最新版本),其實一致性還有其餘級別的:
可用性的值域能夠定義成0到100%的連續區間。
因此,CAP理論定義的實際上是在容忍網絡分區的條件下,「強一致性」和「極致可用性」沒法同時達到。
參考資料:
擴展閱讀:
相信你們讀到這裏,對分佈式/微服務已經有必定的瞭解了,其實單從概念來講,是很是容易理解的。只是極可能被它的名字給唬住了。
下面我就來說講SpringCloud最基礎的知識~
前面也講了,從分佈式/微服務的角度而言:就是把咱們一大的項目,分解成多個小的模塊。這些小的模塊組合起來,完成功能。
舉個可能不太恰當的例子(現實可能不會這麼拆分,但意思到位就行了):
拆分出多個模塊之後,就會出現各類各樣的問題,而SpringCloud提供了一整套的解決方案!
SpringCloud的基礎功能:
SpringCloud的高級功能(本文不講):
那會出現什麼問題呢??首當其衝的就是子系統之間的通信問題。子系統與子系統之間不是在同一個環境下,那就須要遠程調用。遠程調用可能就會想到httpClient,WebService等等這些技術來實現。
既然是遠程調用,就必須知道ip地址,咱們可能有如下的場景。
功能實現一:A服務須要調用B服務
http://123.123.123.123:8888/java3y/3
功能實現二:A服務調用B服務,B服務調用C服務,C服務調用D服務
http://123.123.123.123:8888/java3y/3
,(一樣地)B->C,C->D功能實現三:D服務調用B服務,B服務調用C服務
http://123.123.123.123:8888/java3y/3
,(一樣地)B->C萬一,咱們B服務的IP地址變了,想一想會出現什麼問題:A服務,D服務(等等)須要手動更新B服務的地址
爲了解決微服務架構中的 服務實例維護問題(ip地址), 產生了大量的 服務治理框架和產品。 這些框架和產品的實現都圍繞着服務註冊與服務發現機制來完成對微服務應用實例的 自動化管理。
在SpringCloud中咱們的服務治理框架通常使用的就是Eureka。
咱們的問題:
Eureka是這樣解決上面所說的狀況的:
A、B、C、D四個服務均可以拿到Eureka(服務E)那份註冊清單。A、B、C、D四個服務互相調用再也不經過具體的IP地址,而是經過服務名來調用!
Eureka專門用於給其餘服務註冊的稱爲Eureka Server(服務註冊中心),其他註冊到Eureka Server的服務稱爲Eureka Client。
在Eureka Server通常咱們會這樣配置:
register-with-eureka: false #false表示不向註冊中心註冊本身。 fetch-registry: false #false表示本身端就是註冊中心,個人職責就是維護服務實例,並不須要去檢索服務
Eureka Client分爲服務提供者和服務消費者。
若是在網上看到SpringCloud的某個服務配置沒有"註冊"到Eureka-Server也不用過於驚訝(可是它是能夠獲取Eureka服務清單的)
eureka: client: register-with-eureka: false # 當前微服務不註冊到eureka中(消費端) service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
下面是Eureka的治理機制:
服務提供者
服務消費者
Eureka Server(服務註冊中心):
最後,咱們就有了這張圖:
舉個例子:
優秀博文:
經過Eureka服務治理框架,咱們能夠經過服務名來獲取具體的服務實例的位置了(IP)。通常在使用SpringCloud的時候不須要本身手動建立HttpClient來進行遠程調用。
可使用Spring封裝好的RestTemplate工具類,使用起來很簡單:
// 傳統的方式,直接顯示寫死IP是很差的! //private static final String REST_URL_PREFIX = "http://localhost:8001"; // 服務實例名 private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT"; /** * 使用 使用restTemplate訪問restful接口很是的簡單粗暴無腦。 (url, requestMap, * ResponseBean.class)這三個參數分別表明 REST請求地址、請求參數、HTTP響應轉換被轉換成的對象類型。 */ @Autowired private RestTemplate restTemplate; @RequestMapping(value = "/consumer/dept/add") public boolean add(Dept dept) { return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class); }
爲了實現服務的高可用,咱們能夠將服務提供者集羣。好比說,如今一個秒殺系統設計出來了,準備上線了。在11月11號時爲了可以支持高併發,咱們開多臺機器來支持併發量。
如今想要這三個秒殺系統合理攤分用戶的請求(專業來講就是負載均衡),可能你會想到nginx。
其實SpringCloud也支持的負載均衡功能,只不過它是客戶端的負載均衡,這個功能實現就是Ribbon!
負載均衡又區分了兩種類型:
客戶端負載均衡(Ribbon)
服務端負載均衡(Nginx)
因此,咱們的圖能夠畫成這樣:
Ribbon是支持負載均衡,默認的負載均衡策略是輪詢,咱們也是能夠根據本身實際的需求自定義負載均衡策略的。
@Configuration public class MySelfRule { @Bean public IRule myRule() { //return new RandomRule();// Ribbon默認是輪詢,我自定義爲隨機 //return new RoundRobinRule();// Ribbon默認是輪詢,我自定義爲隨機 return new RandomRule_ZY();// 我自定義爲每臺機器5次 } }
實現起來也很簡單:繼承AbstractLoadBalancerRule類,重寫public Server choose(ILoadBalancer lb, Object key)
便可。
SpringCloud 在CAP理論是選擇了AP的,在Ribbon中還能夠配置重試機制的(有興趣的同窗能夠去搜搜)~
舉個例子:
優秀博文:
到目前爲止,咱們的服務看起來好像挺好的了:可以根據服務名來遠程調用其餘的服務,能夠實現客戶端的負載均衡。
可是,若是咱們在調用多個遠程服務時,某個服務出現延遲,會怎麼樣??
在高併發的狀況下,因爲單個服務的延遲,可能致使全部的請求都處於延遲狀態,甚至在幾秒鐘就使服務處於負載飽和的狀態,資源耗盡,直到不可用,最終致使這個分佈式系統都不可用,這就是「雪崩」。
針對上述問題, Spring Cloud Hystrix實現了斷路器、線程隔離等一系列服務保護功能。
Hystrix提供幾個熔斷關鍵參數:滑動窗口大小(20)、 熔斷器開關間隔(5s)、錯誤率(50%)
Hystrix還有請求合併、請求緩存這樣強大的功能,在此我就不具體說明了,有興趣的同窗可繼續深刻學習~
Hystrix儀表盤:它主要用來實時監控Hystrix的各項指標信息。經過Hystrix Dashboard反饋的實時信息,能夠幫助咱們快速發現系統中存在的問題,從而及時地採起應對措施。
啓動時的頁面:
監控單服務的頁面:
咱們如今的服務是這樣的:
除了能夠開啓單個實例的監控頁面以外,還有一個監控端點 /turbine.stream
是對集羣使用的。 從端點的命名中,能夠引入Turbine, 經過它來聚集監控信息,並將聚合後的信息提供給 HystrixDashboard 來集中展現和監控。
舉個例子:
參考資料:
上面已經介紹了Ribbon和Hystrix了,能夠發現的是:他倆做爲基礎工具類框架普遍地應用在各個微服務的實現中。咱們會發現對這兩個框架的使用幾乎是同時出現的。
爲了簡化咱們的開發,Spring Cloud Feign出現了!它基於 Netflix Feign 實現,整合了 Spring Cloud Ribbon 與 Spring Cloud Hystrix, 除了整合這二者的強大功能以外,它還提
供了聲明式的服務調用(再也不經過RestTemplate)。
Feign是一種聲明式、模板化的HTTP客戶端。在Spring Cloud中使用Feign, 咱們能夠作到使用HTTP請求遠程服務時能與調用本地方法同樣的編碼體驗,開發者徹底感知不到這是遠程方法,更感知不到這是個HTTP請求。
下面就簡單看看Feign是怎麼優雅地實現遠程調用的:
服務綁定:
// value --->指定調用哪一個服務 // fallbackFactory--->熔斷器的降級提示 @FeignClient(value = "MICROSERVICECLOUD-DEPT", fallbackFactory = DeptClientServiceFallbackFactory.class) public interface DeptClientService { // 採用Feign咱們可使用SpringMVC的註解來對服務進行綁定! @RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET) public Dept get(@PathVariable("id") long id); @RequestMapping(value = "/dept/list", method = RequestMethod.GET) public List<Dept> list(); @RequestMapping(value = "/dept/add", method = RequestMethod.POST) public boolean add(Dept dept); }
Feign中使用熔斷器:
/** * Feign中使用斷路器 * 這裏主要是處理異常出錯的狀況(降級/熔斷時服務不可用,fallback就會找到這裏來) */ @Component // 不要忘記添加,不要忘記添加 public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> { @Override public DeptClientService create(Throwable throwable) { return new DeptClientService() { @Override public Dept get(long id) { return new Dept().setDeptno(id).setDname("該ID:" + id + "沒有沒有對應的信息,Consumer客戶端提供的降級信息,此刻服務Provider已經關閉") .setDb_source("no this database in MySQL"); } @Override public List<Dept> list() { return null; } @Override public boolean add(Dept dept) { return false; } }; } }
調用:
基於上面的學習,咱們如今的架構極可能會設計成這樣:
這樣的架構會有兩個比較麻煩的問題:
仍是畫個圖來理解一下吧:
每一個服務都有本身的IP地址,Nginx想要正確請求轉發到服務上,就必須維護着每一個服務實例的地址!
http://123.123.123.123 http://123.123.123.124 http://123.123.123.125 http://123.123.123.126 http://123.123.123.127
購物車和訂單模塊都須要用戶登陸了才能夠正常訪問,基於如今的架構,只能在購物車和訂單模塊都編寫校驗邏輯,這無疑是冗餘的代碼。
爲了解決上面這些常見的架構問題,API網關的概念應運而生。在SpringCloud中了提供了基於Netfl ix Zuul實現的API網關組件Spring Cloud Zuul。
Spring Cloud Zuul是這樣解決上述兩個問題的:
Zuul天生就擁有線程隔離和斷路器的自我保護功能,以及對服務調用的客戶端負載均衡功能。也就是說:Zuul也是支持Hystrix和Ribbon。
關於Zuul還有不少知識點(因爲篇幅問題,這裏我就不細說了):
Zuul支持Ribbon和Hystrix,也可以實現客戶端的負載均衡。咱們的Feign不也是實現客戶端的負載均衡和Hystrix的嗎?既然Zuul已經可以實現了,那咱們的Feign還有必要嗎?
或者能夠這樣理解:
有了Zuul,還須要Nginx嗎?他倆能夠一塊兒使用嗎?
參考資料:
隨着業務的擴展,咱們的服務會愈來愈多,愈來愈多。每一個服務都有本身的配置文件。
既然是配置文件,給咱們配置的東西,那不免會有些改動的。
好比咱們的Demo中,每一個服務都寫上相同的配置文件。萬一咱們有一天,配置文件中的密碼須要更換了,那就得三個都要從新更改。
在分佈式系統中,某一個基礎服務信息變動,都 極可能會引發一系列的更新和重啓
Spring Cloud Config項目是一個解決分佈式系統的配置管理方案。它包含了Client和Server兩個部分,server提供配置文件的存儲、以接口的形式將配置文件的內容提供出去,client經過接口獲取數據、並依據此數據初始化本身的應用。
SpringCloud Config其餘的知識:
使用SpringCloud Config可能的疑問:application.yml和 bootstrap.yml區別
本文主要寫了SpringCloud的基礎知識,但願你們看完能有所幫助~
SpringCloud的資料也不少,我整理一些我認爲比較好,想要深刻的同窗不妨看看下邊的資源~~~
SpringCloud系列文章參考資料:
參考書籍:
SpringCloud GitHub Demo(看完文章的同窗能夠本身練手玩玩,寫好了ReadMe了):
若是想看更多的 原創技術文章,歡迎你們關注個人 微信公衆號:Java3y。Java技術 羣討論:742919422。公衆號還有 海量的視頻資源哦,關注便可免費領取。
可能感興趣的連接: