前幾天魯班LB跟我說:你玩把游戲都要半個鍾啦,為何不用這時間來看看書,如果漲工資還可以幫我買個皮膚。
面對如此合理的這需求,但我不以為然,事實上並不是我不想學習,而是 ↓
實力不允許呀~
直到有一天,突然被叫到會議室,心里疙瘩一下,這難道?項目出嚴重Bug了,冷靜的我思索片刻后,很快就會否定了這種想法,結果巴拉巴拉2小時后,結論竟然是說:“現在我們這個項目要求重構,需用使用微服務架構,所以不了解相關技術的同事請利用這段時間學習復習一下,下個月要開始進入開發階段。
呵呵,會議上,總是有人把微服務吹的很厲害似的,我笑而不語,於是
一周后
以下是我的筆記,我一般是帶着問題去學習,有了需求,或者說是好奇心,因為這樣學習的效率會更高
當看到我們架構中有Eureka,我的第一個問題自然就是:做微服務為什么要使用Eureka,或者Eureka能夠幫助我們解決什么樣的問題?
對於微服務的概念有經驗的開發人員的一般都聽說過吧,無非就是把大應用拆分為小應用,然后處理好服務的相互通訊即可,但是如果光啟動微服務時,不啟動eureka,其他微服務也是可以通過Nginx反向代理,用rest的方式從不同服務后台獲取到數據(HTTP直懟),那多個eureka服務豈不是多此一舉嗎?細想一下其實並不是的,我覺得原因有如下:
其一:
如果后端微服務之間,有互相通信,那么在負載均衡時,相同的服務肯定會啟動多個,而且使用不同的端口,這個時候,服務之間就可以通過注冊在eureka中的名稱來找到對方,而不是根據IP+端口號去找對方。反之如果后端微服務之間相互通信,都要知道具體的IP和端口,那開發起來十分麻煩,而IP地址也並不是固定不變的,除非使用域名封裝,所以無論是測試還是開發還是上線都存在問題。
其二:
Eureka注冊中心的作用很大的程度是作用於服務發現和服務心跳,在多個注冊中心的時候,依賴於zuul的負載均衡,保證異常的服務停止,正常的服務加載,保證服務的穩定性。
新手可能不理解這說的是什么意思,沒關系,請往下看,首先我們先說說什么是SpringCloud
SpringCloud是一系列框架的有序集合。它利用SpringBoot的開發便利性巧妙地簡化了分布式系統基礎設施的開發,如服務發現注冊、配置中心、消息總線、負載均衡、 熔斷器、數據監控等,都可以用SpringBoot的開發風格做到一鍵啟動和部署。是一套簡單易懂、易部署和易維護的分布式系統開發工具包。
主要組成如下:
- 服務發現——Netflix Eureka 服務調用——Netflix Feign
- 熔斷器——Netflix Hystrix 服務網關——Netflix Zuul
- 分布式配置——Spring Cloud Config 消息總線 —— Spring Cloud Bus
本文主要介紹Eureka注冊中心
組成原理:
Eureka包含兩個組件: Eureka Server和Eureka Client:
Eureka Server提供服務注冊服務,各個Client節點啟動后,會在Eureka Server中進行注冊,這樣EurekaServer中的服務注冊表中將會存儲所有可用服務節點的信息,服務節點的信息可以在界面中直觀的看到。
Eureka Client是一個java客戶端,用於簡化與Eureka Server的交互,客戶端有一個內置的、使用輪詢(round-robin)負載算法的負載均衡器。在應用啟動后,將會向Eureka Server發送心跳,默認周期為30秒,如果Eureka Server在多個心跳周期內沒有接收到某個節點的心跳,Eureka Server將會從服務注冊表中把這個服務節點移除(默認90 秒)。如果Eureka Server做了集群,Eureka Server之間通過復制的方式完成數據的同步,同時Eureka還提供了客戶端緩存機制,即使所有的Eureka Server都掛掉,客戶端依然可以利用緩存中的信息消費其他服務的API。
綜上,Eureka能夠通過心跳檢查、客戶端緩存等機制,確保了系統的高可用性。
問題:同為注冊中心,Eureka要比Zookeeper好在哪,或者說為什么Cloud為什么不集成Zookeeper,在CAP理論中說道,一個分布式系統不可能同時滿足C(一致性)、A(可用性)和P(分區容錯性)。由於分區容錯性在是分布式系統中必須要保證的,因此我們只能在A和C之間進行權衡。我們從需求出發考慮,當向注冊中心查詢服務列表時,我們可以容忍注冊中心返回的是幾分鍾以前的注冊信息,但不能接受服務直接down掉不可用。也就是說,對於服務注冊功能對可用性的要求要高於一致性。
Eureka不會出現這種問題,Zookeeper則會出現這樣一種情況,當master節點因為網絡故障與其他節點失去聯系時,剩余節點會重新進行leader選舉。選舉leader的時間太長,30 ~ 120s, 且選舉期間整個zk集群都是不可用的,這就導致在選舉期間注冊服務癱瘓。在雲部署的環境下,因網絡問題使得zk集群失去master節點是較大概率會發生的事,雖然服務能夠最終恢復,但是漫長的選舉時間導致的注冊長期不可用是不能容忍的。
而在此Zookeeper保證的是CP, 而Eureka則是AP,顯然Eureka更加合適。
但在默認配置中,Eureka Server在默認90s沒有得到客戶端的心跳,則注銷該實例,但是往往因為微服務跨進程調用,網絡通信往往會面臨着各種問題,比如微服務狀態正常,但是因為網絡分區故障時,Eureka Server注銷服務實例則會讓大部分微服務不可用,這很危險,因為服務明明沒有問題。為了解決這個問題,Eureka 有自我保護機制,通過在Eureka Server配置參數,可啟動保護機制它的工作原理是:當Eureka Server節點在短時間內丟失過多的客戶端時(可能發送了網絡故障),那么這個節點將進入自我保護模式,不再注銷任何微服務,當網絡故障回復后,該節點會自動退出自我保護模式。
實戰:
Eureka服務端開發(非常簡單的3步完成)
1.從官網下載腳手架項目https://start.spring.io/
2.修改一下配置文件
3.啟動,本質上也是一個SpringBoot項目
把下載好的Demo導入編譯器,打開application.properties或 .yml配置文件
#配置端口 server: port: 8761 #服務端口
#配置服務名稱
spring:
application:
name: service-name #是否將自己注冊到Eureka服務中,本身就是服務端,所以無需注冊
#是否從Eureka中獲取注冊信息
#客戶端和服務端交互地址 eureka: client: registerWithEureka: false fetchRegistry: false serviceUrl: defaultZone: http://127.0.0.1:${server.port}/eureka/
配置啟動類
@SpringBootApplication
//加入注解,聲明為服務端 @EnableEurekaServer public class EurekaServer { public static void main(String[] args) { SpringApplication.run(EurekaServer.class, args); } }
上圖為Eureka服務端啟動成功,可視化界面,Application表示當前並無客戶端用戶注冊進來,這里說的客戶端就是我們開發的微服務應用
Eureka客戶端開發(其實就是我們真正業務微服務應用)
1.從官網下載腳手架項目https://start.spring.io/
2.修改一下配置文件
#配置端口
server:
port:1111
#配置服務名稱
spring:
application:
name : client-name
#配置服務器路徑
eureka: client: service‐url: defaultZone: http://localhost:8761/eureka instance: prefer‐ip‐address: true
啟動類配置
//加入注解,聲明為微服務客戶端,項目啟動后自動向服務端注冊
@EnableDiscoveryClient @SpringBootApplication public class ServiceProviderApplication { public static void main(String[] args) { SpringApplication.run(ServiceProviderApplication.class, args); } }
啟動后就能在服務端可視化界面看見客戶端的注冊信息,我們現在就將所有的微服務都注冊到Eureka中,這樣所有的微服務之間都可以互相調用,服務的調用將在下一篇文章詳細講解
但是有時候會出現下面的文字
說明Eureka已經進入了保護模式:
Eureka Server在運行期間,會統計心跳失敗的比例在15分鍾之內是否低於85%,如果出現低於的情況(在生產環境上通常是由於網絡不穩定導致),Eureka Server會將當前的實例注冊信息保護起來,同時提示這個警告。保護模式主要用於一組客戶端和Eureka Server之間存在網絡分區場景下的保護。一旦進入保 護模式,Eureka Server將會嘗試保護其服務注冊表中的信息,不會注銷任何微服務。
關於Eureka Server集群的介紹
Eureka注冊中心只部署在一台機器上,一旦出現問題,會導致整個服務調用系統的崩潰,針對這種情況,我們需要部署兩台Eureka注冊中心,彼此相互注冊,組成一個高可用的的Eureka集群。這樣一來,每台服務器都包含着對方的服務注冊信息,相當於雙機熱備,同時,服務提供者只需向其中的一個注冊服務。
在生產環境中,一般是把兩個相互注冊的服務器安裝在兩台服務器上,現在我們在一台機器上模擬雙服務器的場景,具體的實現步驟如下:
到C:\WINDOWS\system32\drivers\etc目錄里,找到hosts文件,在其中加入兩個機器名(其實都是指向本機),代碼如下。修改后,需要重啟機器。
127.0.0.1 erueka-server
127.0.0.1 erueka-server2
配置如下
Eureka service
server: port: 8761 #端口號
spring:
application:
name: eureka-server #應用名
eureka: instance: hostname: hostname1 client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://hostname1:8761/eureka/,http://hostname2:8762/eureka/
Eureka service2
server: port: 8762 #端口號 spring: application: name: eureka-server2 #應用名 eureka: instance: hostname: hostname2 client: register-with-eureka: true fetch-registry: true service-url: defaultZone: http://hostname1:8761/eureka/,http://hostname2:8762/eureka/
這樣下來,就算有一台機器死機了,然后可讓服務正常工作。