SpringCloud入門簡述
1、微服務簡述
微服務,是一個小型的服務,也是一種設計理念,將一個大型繁雜的系統拆分為多個小型的服務,進行獨立部署,這些服務在獨立進程中運行,通過特定的協議進行通訊
優點:
- 輕量化:一個服務不再像一個系統一個繁雜,更加小巧,功能相對單一
- 低耦合:不同的服務模組之間的依賴性降低,可以更加專註於一個功能的開發
- 靈活性高:可以進行獨立的部署,也可以支援不同開發語言之間進行服務的調用
缺點:
- 運維成本高:微服務架構項目往往是由多個微服務構成,隨著服務的增多,項目出現異常時不易查詢根源
- 重複性高:微服務的工具類不能夠被其他服務調用,所以每個微服務都需要進行重複添加該類,導致重複
- 介面調整成本高:一個被多個服務調用的服務一旦更改了介面,那麼其他的介面也要做相應的修改,這一修改造成的成本會明顯提高
1.1 常見的微服務框架
- SpringCloud:SpringBoot基礎上構建的微服務框架,通用組件較多,通訊方式基於HTTP的rest方式
- Dubbo:阿里巴巴的服務框架,使用RPC通訊
在服務通訊性能上RPC更強,但是Rest更為靈活
1.2 微服務經常考慮的問題
- 網關:提供統一的服務入口
- 服務間調用
- 服務發現:負載均衡時發現可用服務,下線不可用
- 容錯:服務調用失敗的處理方式
- 熔斷:在特定場景下關閉服務的調用,防止錯誤的擴散
- 限流和降級:請求數量過載,進行請求拒絕(限流)或者返回一個預先設置的返回值(降級)
2、SpringCloud簡述
SpringCloud是基於SpringBoot實現的微服務框架,為開發人員提供了很多快速構建分散式系統中常見模式的工具,包括配置管理、服務發現、斷路器、智慧路由、微代理,控制匯流排等。
2.1 常用的一些組件
- Netflix-Eureka:服務註冊與發現
- Netflix-Ribbon:負載均衡,分發請求到不同的伺服器,緩解伺服器壓力
- Netflix-Hystrix:服務保護與熔斷機制
- Netflix-Zuul:服務網關
- Feign:服務間通訊
- Config:配置中心
2.2 特點
Spring Cloud專註於為典型的用例提供良好的開箱即用體驗,並為其他用例提供擴展性機制。
- Distributed/versioned configuration——分散式/版本化配置
- Service registration and discovery——服務註冊和發現
- Routing——路由
- Service-to-service calls——服務到服務呼叫
- Load balancing——負載平衡
- Circuit Breakers——斷路器
- Global locks——全局鎖
- Leadership election and cluster state——主節點投選與聚集狀態
- Distributed messaging——分散式消息傳遞
2.3 與SpringBoot的區別
- SpringBoot是基於Spring的快速配置腳手架,而SpringCloud是基於SpringBoot的雲應用開發工具
- SpringBoot專註於開發單個微服務,SpringCloud關注全局的微服務協調治理框架,用於整合管理SpringBoot開發的一個個微服務
- SpringBoot可以離開SpringCloud獨立開發使用,而SpringCloud離不開SpringBoot
參考地址:
- Spring Cloud中文網-官方文檔中文版://www.springcloud.cc
- Spring Cloud中文API文檔://www.springcloud.cc/spring-cloud-dalston.html
- Spring Cloud中國社區://springcloud.cn/
3、Eureka 服務註冊和發現
Eureka是Netflix開發的基於Rest的服務發現框架,SpringCloud基於此進行二次封裝,實現服務的管理。
創建一個Eureka服務://www.cnblogs.com/william-m/p/15991511.html
如果沒有Eureka,如何進行服務之間的調用?
使用Rest進行調用,先將RestTemplate註冊到Bean,然後:
@RestController
public class MyController {
private static final String REST_URL_PREFIX="//localhost:8082";
@Autowired
private RestTemplate restTemplate;
@GetMapping("user/getAll")
public User getById(@RequestParam Long id){
return restTemplate.getForObject(REST_URL_PREFIX+"/user/getAll/"+id,User.class);
}
}
3.1 三個角色
-
註冊中心
Eureka Server,可以讓其他服務將相關資訊註冊進去,然後讓相關服務發現這些服務並來調用
-
服務提供者
Eureka Client,將自身註冊進Server中,提供自身的主機,埠,運行狀況指示器URL,主頁和其他詳細資訊讓其他服務去發現,一般都是完成某些具體業務的服務
-
服務消費者
Eureka Client,將自身註冊進Server中,發現服務提供者並調用其相關介面,一般僅提供介面供外部調用,然後調用服務提供者的介面完成具體的業務
3.2 AP原則
C – consistency 強一致性
A – availability 可用性
P – partition tolerance 分區容錯性
Eureka遵循的是AP原則,Eureka各個節點都是平等的,部分服務節點的下線不會影響正常服務的調用,只要該服務還剩下一個節點在線就可以進行正常的服務訪問,即保證了服務可用,但是並不能保證查詢到的資訊是最新的。Zookeeper的CP原則與之不同,Zookeeper會有一個master節點來保證一致性,一旦master節點掛掉,剩餘的節點會重新選舉一個leader,而選擇的過程需要時間,這期間會使得該服務癱瘓,所以需要滿足高可用的話該情況是不能夠容忍的。
4、Ribbon 負載均衡
Spring Cloud Ribbon是一個基於HTTP和TCP的客戶端負載均衡工具,基於Netflix Ribbon實現,通過輪詢、隨機等演算法選擇一個可用服務。
目的:將用戶的請求平攤的分配到多個服務上,實現高可用
4.1 客戶端負載均衡與伺服器端負載均衡的區別
最大區別:服務清單所存儲的位置
- 伺服器端負載均衡
客戶端先發送請求到負載均衡伺服器,然後由負載均衡伺服器通過負載均衡演算法,在眾多可用的伺服器之中選擇一個來處理請求。
- 客戶端負載均衡
客戶端自己維護一個可用伺服器地址列表,在發送請求前先通過負載均衡演算法選擇一個將用來處理本次請求的伺服器,然後再直接將請求發送至該伺服器。
4.2 服務調用
邏輯時序:RestTemplate發起請求 → 負載均衡器攔截器攔截 → LoadBalanceClient獲取ILoadBalance → 獲取服務列表 → 根據負載均衡器選擇一個server → 發起請求 → 記錄調用資訊
4.3 負載均衡演算法重寫
public class MyBalanceRule extends AbstractLoadBalancerRule {
// 繼承AbstractLoadBalancerRule並重寫choose演算法
@Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
}
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
}
Server server = null;
while (server == null) {
if (Thread.interrupted()) {
return null;
}
List<Server> upList = lb.getReachableServers(); // 獲取活著的服務
List<Server> allList = lb.getAllServers(); // 獲取所有服務
int serverCount = allList.size();
if (serverCount == 0) {
return null;
}
// =============================================
// 自定義負載均衡演算法
// server = ......
//===============================================
if (server == null) {
Thread.yield();
continue;
}
if (server.isAlive()) {
return (server);
}
server = null;
Thread.yield();
}
return server;
}
}
// 添加配置類,指定負載均衡演算法
@Configuration
public class MyRuleConfig {
@Bean
public IRule myRule(){
return new MyBalanceRule();
}
}
5、Feign負載均衡
Feign是聲明式的 web service 客戶端,SpringCloud對Feign進行了封裝,可以與Ribbon和Eureka使用以支援負載均衡,只需要創建一個介面並添加@FeignClient(“服務名”)註解即可。
5.1 Feign和Ribbon的區別
-
Application註解
Ribbon使用@RibbonClient
Feign使用@EnableFeignClients
-
服務的指定
Ribbon在@RibbonClient註解上聲明
Feign在介面中使用@FeignClient聲明
-
服務的調用
Ribbon基於HTTP和TCP客戶端的負載均衡器可以自己構建HTTP請求,使用RestTemplate發送服務
Feign基於Ribbon進行改進,採用介面的方式,將需要調用的服務的方法定義成抽象方法
5.2 Feign的使用
Consumer應用
啟動類
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ChannelApplication.class, args);
}
}
為了調用Product應用服務的介面類
@FeignClient(value = "Product")
public interface ProductService {
@RequestMapping(value = "/user/selectById", method = RequestMethod.GET)
User selectById(@RequestParam(value = "id") Long id);
}
Product應用
controller
@RequestMapping("/user")
@RestController
public class ProductController {
@RequestMapping(value = "selectById", method = RequestMethod.GET)
User selectById(@RequestParam(value = "id") Long id){
return "";
}
}
6 、Hystrix 熔斷
Hystrix是一個服務容錯與保護的組件,用於服務降級、服務熔斷、服務限流等等,能夠保證在其中一個服務出現問題的時候,不會出現級聯故障,防止雪崩,提高分散式服務的健壯性。
服務雪崩:微服務之間進行調用的時候,服務F同時被多個服務A、B、C、D調用,此時服務F發生故障(響應時間過長或者不可用等),對於服務ABCD的調用會佔用越來越多的系統資源,引起系統整體的崩潰。
也就是說一個微服務的失敗會引發整個系統的崩潰,像雪崩一樣。
6.1 服務降級
將某些服務停掉會i這不進行業務處理,釋放資源來維持主要服務的功能。
6.1.1 使用場景:
- 伺服器壓力劇增,為了保證核心業務的正常運行,對於一些不重要的服務進行有策略地不處理或者簡單處理,保證不會和核心業務搶佔資源
- 某些服務不可用時,為了避免長時間的等待造成服務的卡頓雪崩,調用該服務時執行備用的降級邏輯,返回友好的提示,保障主題業務不受故障影響
6.1.2 降級方式
- 介面拒絕服務:頁面可以訪問,進行增刪改時提示伺服器繁忙
- 頁面拒絕服務:頁面提示繁忙他,跳轉到其他靜態頁面
- 延遲持久化:涉及增刪改時提示稍後查看結構,不立即處理,將數據添加到非同步隊列,伺服器空閑時處理
- 隨機拒絕服務:隨機拒絕用戶的訪問,用戶體驗差,較少採用
6.2 服務熔斷
應對服務雪崩的一種保險措施,是微服務的鏈路保護機制,是服務降級的一種特殊處理方式。
為了應對某個服務故障的情況,保證系統的整體可用性,熔斷器會切斷對該服務的請求,返回一個比較友好的錯誤響應,直到服務恢復正常
6.2.1 三種狀態
熔斷機制的三種狀態:
- 熔斷關閉狀態:業務正常訪問時,熔斷器關閉,服務可以正常調用
- 熔斷開啟狀態:服務調用出錯率達到閾值,開啟熔斷,對該服務的所有請求將會被切斷,執行降級方法
- 半熔斷狀態:服務開啟一段時間後進入半熔斷狀態,嘗試恢復服務的調用,允許部分請求的調用並同時進行監控,如果成功率達到預期,則關閉熔斷器,恢復服務的正常調用,否則開啟熔斷。
6.2.2 實現步驟
- 當服務出現故障使得服務的調用失敗率達到一個閾值,熔斷器開啟
- 在熔斷器開啟時,對該服務的調用會轉向設置的fallback降級方法,防止雪崩
- 當熔斷器開啟達到一定的時間,進入半熔斷狀態,允許部分請求的調用,同時監控其成功率
- 如果該服務的調用成功率達到預期,關閉熔斷器,恢復原有服務的調用邏輯,否則繼續開啟熔斷,重複234
示例:
// 在getUserById方法出現故障時執行getUserFallBack方法
@HystrixCommand(fallbackMethod = "getUserFallBack")
@GetMapping(value="getUserNameById")
public String getUserById(Long id){
return UserService.selectById(id);
}
public String getUserFallBack(){
return "請稍後再試";
}
6.3 熔斷、降級、限流處理服務
熔斷:直接切斷服務的調用
降級:犧牲非核心業務保證核心服務的正常
限流:服務訪問量達到閾值後拒絕多餘的調用
7、Zuul網關
Zuul是一個微服務網關。網關:是一個網路系統的前置入口。也就是說要想訪問一個有網關的網路系統請求相應的服務,需要先進入網關,然後路由到相應的服務。
通常是組成一個系統的微服務很多、或者有許可權要求時需要用到網關。
7.1 網關的作用
-
統一入口
為全部的服務提供一個統一的入口,將內外隔離,保障了服務的安全性
(如:多個微服務組成的系統擁有一個統一的請求入口)
-
鑒權校驗
識別每一個請求的許可權,拒絕不符合要求的請求
(如:校驗用戶的請求許可權)
-
動態路由
動態地將請求路由到不同的後端集群中
-
減少耦合
減少客戶端和服務端的耦合程度,使得服務可以獨立發展,通過網關層來映射
7.2 過濾器
Zuul提供一個過濾器,父類為ZuulFilter,用來過濾代理請求,提供額外的功能邏輯(這點類似於AOP),包括前置過濾、路由後過濾、後置過濾、異常過濾。
ZuulFilter包含的抽象方法:filterType、filterOrder、shouldFilter、run
-
filterType
返回一個字元串,代表過濾器的類型
- pre:前置過濾,在請求路由之前執行,如:身份認證、日誌記錄等
- router:在路由執行後,服務調用前被調用
- error:處理請求發生錯誤時調用
- post:請求到達服務之後執行,如:添加響應頭,記錄響應日誌
-
filterOrder
過濾器的執行順序,數值越小,優先順序越高
-
shouldFilter
是否執行該過濾器,true,false
-
run
執行相關業務邏輯
8、Config配置中心
當微服務眾多的時候,想要管理各個服務的配置時過於繁雜,SpringCloud Config則可以用來對每個微服務的配置進行集中的管理。可以實現許可權管控、灰度發布、版本管理、格式檢驗、安全配置等。
灰度發布:在進行產品研發時,新版本的發布可能存在一定的風險,那麼讓一部分用戶繼續使用A特性,並且提供B特性讓部分用戶使用,如果B特性口碑良好,產品穩定,就可以逐漸進行用戶的遷移。灰度發布保證發生問題可以及時解決。就像是打遊戲有個測試版本,如果測試用戶對該版本滿意,則可以繼續發布到正式,用戶不滿意就能及時補救,反正沒有發布到正式。
作用:
- 集中管理配置文件
- 在服務運行期間實現動態的配置刷新
- 實現屬性值的加密解密
- 可以實現基於GIT進行版本管理
特點:
- 中心化管理
- 不限語言
- 靈活的版本控制