分散式是現在網際網路架構的首選。在分散式中我們會有三方理論簡稱CAP
簡稱 | 全稱 | 解釋 |
---|---|---|
C | Consistency | 資料一致性 |
A | Availability | 可用性,效能 |
P | Partition tolerance | 分割槽容錯性 |
> 今天我們就來看看分散式中關於服務治理這塊的服務
什麼是服務治理
-
在多個服務之間相互呼叫的時候比較零散,管理起來比較麻煩。當被呼叫者有所改動可能都會牽扯到呼叫者的修改。所以服務治理應運而生。
-
spring cloud的Eureka實現了服務註冊、服務呼叫、負載均衡、容錯。這也是服務治理模組通用功能。
-
服務註冊和服務呼叫在eureka看來都是客戶端。eureka服務是服務端。所以他是一種典型的CS架構。eureka客戶端需要與eureka服務保持心跳機制。這樣eureka服務才會認為客戶端沒有當機。
- 上述的架構圖可以清楚的看出,eureka服務端可叢集化,服務提供者可以叢集化。客戶端就沒必要叢集化。就算叢集化對於eureka服務來說也是單機的consumer。
Eureka呼叫過程
-
service provider啟動時會將自己服務的資訊封裝後註冊到eureka註冊中心上。service consumer已provider註冊名去註冊中心尋找到真實地址並進行呼叫。
-
針對service provider的管理對於service consumer來說不需要知道service provider的具體資訊。只需要知道service provider的註冊名就行了。在我們叢集化後也不用擔心provider我們具體的呼叫地址。負載均衡也是eureka幫我分配了。我們客戶端只負責介面的呼叫。
Eureka單機註冊
Eureka 單機啟動
- 這裡我們不做spring其他的解釋,詳細請看git分支詳細程式碼
<dependency>
<groupid>org.springframework.cloud</groupid>
<artifactid>spring-cloud-starter-netflix-eureka-server</artifactid>
</dependency>
-
在我們新建的專案中pom檔案中新增如上gva。就會將eureka服務端功能注入。下面我們只需要新增一些配置啟動就行了。
-
新增依賴後我們在springboot專案中yml中新增如下配置
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false #表示該模組作為eureka服務,自己是不需要想自己註冊的,註冊了只是徒增煩惱
fetch-registry: false # 表示自己就是註冊中心。自己是管理者不是被管理者。
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
- 最後我們在spiringboot啟動類上開啟eurekaserver就行了。
@EnableEurekaServer
- 能夠訪問說明我們的eureka服務正常啟動。現在沒有客戶端註冊上來。所以現在看到DS Replicas列表是空的。
單機註冊
-
上面我們已經單機啟動了eureka服務。下面我們看看服務註冊是否可以。我們已之前payment模組為例。
-
pom中新增client座標
<dependency>
<groupid>org.springframework.cloud</groupid>
<artifactid>spring-cloud-starter-netflix-eureka-client</artifactid>
</dependency>
- yml中填入地址
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka
- 主啟動類上新增註解
@EnableEurekaClient
叢集註冊
-
現在我們多開幾個payment進行註冊
-
因為我們是在idea中開發的。還沒有打成jar包。也是為了方便除錯這裡通過idea直接複製的payment專案
- 現在我們看看我們本地idea啟動專案的情況 , payment已經有兩個了分別是8001,8002
- 現在我們看到eureka服務上也出現了8001,8002了
客戶呼叫
-
還記得我們的feature/cloud-pre上order模組是如何呼叫payment的嗎。是的我們通過resetTemplate進行http方式呼叫的。現在我們還是通過他進行呼叫只不過呼叫地址是payment註冊在eureka上的服務名。
-
這裡客戶端如何註冊和payment配置一樣的。因為雖然是order呼叫payment,但是對於eureka來說payment和order都是客戶端。所以配置都是一樣的。
- 現在在單機的eureka上我們看到了單機的order服務和叢集的payment服務。下面我們order呼叫payment的地方做如下修改
- 只是呼叫跟地址進行了修改。當然前提是restTemplate支援了負載均衡。
- 下面結果如何讀者可以自行測試了。
http://localhost/order/getpayment/123
針對這個介面呼叫多次。會發現返回結果裡的服務埠會不斷的8001,8002切換。因為restTemplate預設是輪詢的。而我們這裡payment提供了兩個服務。到這裡我們就實現了eureka單機版的服務註冊及呼叫
Eureka叢集註冊
- 上面是單機的eurake。下面我們看看eurake叢集如何配置。對於eureka客戶端來說註冊到eureka叢集上來說非常簡單。
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka,http://www.eureka2/eureka
-
像上述一樣defaultZone後面直接追加eureka服務就行了。正常叢集都是佈置在不同機器上的。所以域名或者ip都是不同的。如果讀者在一臺機器上部署可以通過nginx將不同服務分配到不同域名下。因為在eureka服務端上配置需要用到域名。
-
客戶端是直接追加。eureka服務端改動也不是很多隻需要將hostname配置唯一就行了。
eureka:
instance:
hostname: www.zxhtom1.com #eureka服務端的例項名字
client:
register-with-eureka: false #表識不向註冊中心註冊自己
fetch-registry: false #表示自己就是註冊中心,職責是維護服務例項,並不需要去檢索服務
service-url:
defaultZone: http://eureka7002.com:7002/eureka/
- 所以說如果是單機部署叢集,我們就需要通過nginx轉發下。這裡不贅述
idea 如何同一個專案啟動多次
- 剛才在部署叢集的時候為了方便演示。我們藉助idea啟動多個例項。在裡面分配不同的埠。但是在部署eureka叢集是就沒法搞了。因為需要改變配置檔案內容。我們可以在啟動的時候指定外部配置檔案
Eureka自我保護
為什麼要自我保護
- 上面我們發現有兩個8002的payment。為什麼會出現如此奇怪的問題呢。排查發現一開始我通過idea啟動了8001,8002。然後我又通過引入外部配置檔案的方式重新啟動了8002。這個時候原來的8002例項其實已經掛了。這個時候eureka會認為出現50%的客戶端沒有準時傳送心跳。50<85 這個時候eureka認為大批客戶端可能因為網路波動導致沒有及時回覆。eureka會開啟自我保護機制。
- 雖然上面是個反面列子。也恰恰說明了為什麼需要自我保護。加入這個時候8002在其他機器上因為網路延遲被踢出就會出現冤假錯案。所以這也解釋了為什麼上述出現兩個8002.
如何開啟自我保護
- 自我保護的功能是預設開啟的。
eureka.server.enable-self-preservation: false
我們通過此屬性設定false就是關閉自我保護。
自我保護如何啟用
-
其實上面兩個8002是一種意外。我們無意中觸發了自我保護。
-
自我保護機制條件 : 最近一分鐘收到心跳數執行緒佔匯流排程85%以下。
-
低於85%說明沒有指定活躍數進行心跳回復,所以認為是網路波動了。
-
自我保護的臨界值= renews(last min)/renews(threshold)
-
通過計算我們知道是75% 。 如果不算上正常的8002 。 那就是50% 。 所以不管怎麼樣都會觸發自我保護的。
-
自我保護也滿足的開篇提到的CAP原理中的A理論。eureka滿足了高可用性原則。及時客戶端真的當機了也要留下。寧可多留也不錯殺。這樣就會導致資料不一致的情況。