相關概念
網際網路專案架構
網際網路專案架構的特點:
- 使用者多
- 流量大,併發高
- 海量資料
- 易受攻擊
- 功能繁瑣
- 變更快
傳統專案和網際網路專案的不同:
使用者體驗:
- 美觀
- 功能
- 速度
- 穩定性
大型網際網路專案架構的目標:
- 高效能:提供快速的訪問體驗
- 高併發:能夠同時承載大訪問量
- 高可用:能夠長時間穩定提供服務
- 可伸縮:可快速調整服務承載能力
- 高可擴充套件:架構耦合性高,可快速方便地更新子系統/模組
衡量網站的效能指標:
-
響應時間:指執行一個請求從開始到最後收到響應資料所花費的總體時間。
-
併發數:指系統同時能處理的請求數量。
-
併發連線數:每秒鐘伺服器連線的總 TCP 數量(客戶端向伺服器發起請求,並建立了 TCP 連線)。
-
請求數:也稱為 QPS(Query Per Second),即每秒的請求數。
-
併發使用者數:單位時間內有多少使用者。
-
吞吐量:指單位時間內系統能處理的請求數量(通常以 QPS 或 TPS 來衡量)。
- QPS(Query Per Second):每秒查詢(請求)數
- TPS(Transactions Per Second):每秒事務數
一個事務是指一個客戶機向伺服器傳送請求然後伺服器做出反應的過程(即客戶機在傳送請求時開始計時,收到伺服器響應後結束計時,以此來計算使用的時間和完成的事務個數)。
1 個頁面的 1 次訪問,只會形成 1 個 TPS;但 1 次頁面請求,可能產生多次對伺服器的請求,就會有多個 QPS 。
通常:QPS >= 併發連線數 >= TPS
叢集和分散式
- 叢集:一個業務模組,部署在多臺伺服器上。(很多“人”一起,幹一樣的事)
- 分散式:一個大的業務系統,拆分為各個小的子業務系統,分別部署在不同的伺服器上。(很多“人”一起,幹不一樣的事,合起來幹一件大事)
架構演進
Dubbo 是 SOA 時代的產物,SpringCloud 是微服務時代的產物。
單體架構
優點:
- 簡單:開發部署都很方便,小型專案首選。
缺點:
- 專案啟動慢
- 可靠性差
- 可伸縮性差
- 擴充套件性和可維護性差
- 效能低
垂直架構
垂直架構:垂直架構是指將單體架構中的多個模組拆分為多個獨立的專案。形成多個獨立的單體架構。
優點:
- 解決了單體架構的眾多問題。
缺點:
- 重複功能過多。
分散式架構
分散式架構:指在垂直架構的基礎上,將公共業務模組抽取出來,作為獨立的服務供其他呼叫者消費,以實現服務的共享和重用(底層通過 RPC 實現)。
RPC(Remote Procedure Call):遠端過程呼叫。有非常多的協議和技術來都實現了 RPC,比如:HTTP REST 風格、Java RMI 規範、WebService SOAP 協議、Hession 等等。
優點:
- 解決了垂直架構中重複功能過多的問題。
缺點:
- 服務提供方一旦發生變更,所有消費方都需要對應變更。
SOA 架構
SOA(Service- Oriented Architecture,面向服務的架構):是一個元件模型(設計理念),它將應用程式拆分成不同的功能單元(稱為服務),並通過定義良好的介面和契約將各服務聯絡起來。
ESB(Enterparise Servce Bus):企業服務匯流排,服務中介。主要是提供了服務與服務之間的互動。ESB 包含的功能如:負載均衡、流量控制、加密處理、服務監控、異常處理、監控告急等。
微服務架構
-
微服務架構:是在 SOA 上做的昇華,微服務架構強調的一個重點是“業務需要徹底的元件化和服務化”,即原有的單個業務系統會拆分為多個可以獨立開發、設計、執行的小應用,這些小應用之間通過服務完成互動和整合。
-
微服務架構 = 80% 的 SOA 服務架構思想 + 100% 的元件化架構思想 + 80% 的領域建模思想
特點:
- 服務實現元件化:開發者可以自由選擇開發技術,也不需要協調其他團隊。
- 去中心化:每個微服務有自己私有的資料庫持久化業務資料。
- 自動化部署:把應用拆分成為一個個獨立的單個服務,方便自動化部署、測試、運維。
Dubbo 介紹
什麼是 Dubbo ?
- Dubbo 是阿里巴巴公司開源的一個高效能、輕量級的 Java RPC 框架。
- 致力於提供高效能和透明化的 RPC 遠端服務呼叫方案,以及 SOA 服務治理方案。
- 官網: https://dubbo.apache.org
Dubbo 架構:
節點角色說明:
- Provider:暴露服務的服務提供方。
- Contahier:服務執行容器。
- Consumer:呼叫遠端服務的服務消費方。
- Registry:服務註冊與發現的註冊中心。
- Monitor:統計服務的呼叫次數和呼叫時間的監控中心。
Dubbo 環境安裝
ZooKeeper 安裝
Dubbo 入門案例
案例說明:Dubbo 作為一個 RPC 框架,其最核心的功能就是要實現跨網路的遠端呼叫。本示例就是要建立兩個應用,一個作為服務的提供方,一個作為服務的消費方。通過 Dubbo 來實現服務消費方遠端呼叫服務提供方的方法。
- 在服務提供者模組中編寫 UserServicelmpl 提供服務;
- 在服務消費者模組中編寫 UserController 遠端呼叫 UserServicelmpl 提供的服務。
公共介面模組
- UserService.java:
public interface UserService {
public String sayHello();
}
服務提供者模組
- UserServiceImpl.java:
package com.service.impl;
import com.service.UserService;
import org.apache.dubbo.config.annotation.Service;
// Spring的@Service:將該類的物件建立出來,放到Spring的IOC容器中(bean定義)
@Service // dubbo的@Service:將該類提供的方法(服務)對外發布。將訪問的ip、埠、路徑等資訊註冊到註冊中心中
public class UserServiceImpl implements UserService {
public String sayHello() {
return "welcome to dubbo ~";
}
}
- applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 掃描spring相關注解 -->
<!-- <context:component-scan base-package="com.service" />-->
<!-- dubbo的配置 -->
<!-- 1.配置專案的名稱(唯一) -->
<dubbo:application name="dubbo_service"/>
<!-- 2.配置註冊中心的地址 -->
<dubbo:registry address="zookeeper://192.168.3.244:2181"/>
<!-- 3.掃描dubbo相關注解 -->
<dubbo:annotation package="com.service.impl" />
</beans>
服務消費者模組
- UserController.java:
package com.controller;
import com.service.UserService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
// @Autowired // spring的本地注入
@Reference // dubbo的遠端注入
/*
1. 從註冊中心(zookeeper)獲取userService的訪問url
2. 進行遠端呼叫RPC
3. 將結果封裝為一個代理物件。給變數賦值
*/
private UserService userService;
@RequestMapping("/sayHello")
public String sayHello() {
return userService.sayHello();
}
}
- springmvc.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<mvc:annotation-driven/>
<!-- 掃描spring相關注解 -->
<context:component-scan base-package="com.controller"/>
<!-- dubbo的配置 -->
<!-- 1.配置專案的名稱(唯一) -->
<dubbo:application name="dubbo_service">
<!-- qos是dubbo的監聽服務,本例的service和controller部署在單機中,因此會出現埠(55555)衝突 -->
<dubbo:parameter key="qos.port" value="33333"/>
<!-- <dubbo:parameter key="dubbo.port" value="20881"/>-->
</dubbo:application>
<!-- 2.配置註冊中心的地址 -->
<dubbo:registry address="zookeeper://192.168.3.244:2181"/>
<!-- 3.掃描dubbo相關注解 -->
<dubbo:annotation package="com.controller" />
</beans>
測試
分別啟動服務提供者和消費者的服務(Tomcat),訪問消費者的地址 http://localhost:8000/user/sayHello ,檢視瀏覽器輸出結果:
dubbo-admin
- dubbo-admin 是圖形化的服務管理頁面。
- 開源的 Dubbo 的服務管理控制檯是阿里巴巴內部裁剪版本。
- 從註冊中心中獲取到所有的提供者/消費者進行配置管理。
- 開源部分的功能主要包括:路由規則/動態配置/服務降級/訪問控制/權重調整/負載均衡等管理功能。
- dubbo-admin 是一個前後端分離的專案(前端使用 vue,後端使用 springboot),安裝 dubbo-admin 其實就是部署該專案。
安裝
1)環境準備
- JDK
- Maven
- node.js(下載地址)
2)下載 Dubbo-Admin
3)解壓並修改配置檔案
- 解壓後進入 \dubbo-admin-develop\dubbo-admin-server\src\main\resources 目錄,找到 application.properties 配置檔案 修改 zookeeper 相關配置:
# 修改zookeeper的實際IP和埠
# 註冊中心
admin.registry.address=zookeeper://192.168.149.135:2181
# 配置中心
admin.config-center=zookeeper://192.168.149.135:2181
# 後設資料中心
admin.metadata-report.address=zookeeper://192.168.149.135:2181
4)打包專案
在 dubbo-admin-develop 目錄執行打包命令:
# 需等待約5分鐘
mvn clean package -Dmaven.test.skip=true
5)啟動後端服務
# 在 dubbo-Admin-develop\dubbo-admin-distribution\target 目錄
# 執行以下命令啟動 dubbo-admin(dubbo-admin 後臺由 SpringBoot 構建)
java -jar .\dubbo-admin-0.1.jar
6)啟動前端服務
# 在 dubbo-admin-ui 目錄下執行命令
npm run dev
7)訪問
- 瀏覽器輸入 http://localhost:8081/ (使用者名稱密碼都是 root):
簡單使用
搜尋(服務生產者提供的)服務:
檢視服務詳情:
注意:
- 服務需要被訪問過後,才會在頁面服務資訊中展示。
- 後設資料資訊需要在服務生產者的 spring 配置檔案中增加以下配置,再次開啟 dubbo-admin 即可顯示:
<!-- 後設資料配置 -->
<dubbo:metadata-report address="zookeeper://192.168.149.135:2181" />
核心功能:
Dubbo 高階特性
序列化
- Dubbo 內部已經將序列化和反序列化的過程內部封裝了,我們只需要在定義 pojo 類時實現 serializable 介面即可。
- 一般我們會定義一個公共的 pojo 模組,讓生產者和消費者都依賴該模組。
地址快取
當註冊中心掛了,服務是否可以正常訪問?**
- 可以,因為 Dubbo 服務消費者在第一次呼叫時,會將服務提供方的地址快取到本地,之後再呼叫時無需再訪問註冊中心。
- 當服務提供者地址發生變化時,註冊中心會通知服務消費者,以便更新快取。
超時
- 當服務消費者在呼叫服務提供者的時候發生了阻塞、等待的情形時,服務消費者會直等待下去。
- 在某個峰值時刻,大量的請求都在同時請求服務消費者時,會造成執行緒的大量堆積,勢必會造成雪崩。
- Dubbo 利用超時機制來解決這個問題:在設定的時間段內,當無法完成服務訪問則自動斷開連線。
// 使用 timeout 屬性配置超時時間,預設值1000,單位毫秒
@Service(timeout=3000)
重試
- 僅設定超時的問題:如果出現網路抖動,則這一次請求就會失敗。
- 為此,Dubbo 還提供了重試機制來避免類似問題的發生。
// 通過retries屬性來設定重試次數。預設為2次
@Service(timeout=3000, retries=3) // 嘗試連線4次(1+3)
多版本
-
灰度釋出:當出現新功能時,會讓一部分使用者先使用新功能,使用者反饋沒問題時,再將所有使用者遷移到新功能。
-
Dubbo 中使用 version 屬性來設定和呼叫同一個介面的不同版本。
// 生產者配置
@Service(version = "v1.0") // 版本一
public class UserServiceImp11 implements UserService {...}
@Service(version = "v2.0") // 版本二
public class UserServiceImp12 implements UserService {...}
// 消費者配置
@Reference(version = "v2.0") // 遠端注入版本二
private UserService userService;
負載均衡
Dubbo 的 4 種負載均衡策略:
- Random:按權重設定隨機概率,預設策略。
- RoundRobin:按權重輪詢。
- LeastActive:最少活躍呼叫數,即每次選取上一次呼叫時長最短的服務(相同活躍數則隨機)。
- ConsistentHash:一致性 Hash,相同引數的請求總是發到同一提供者。
// 生產者 1 配置
@Service(weight = 100)
public class UserServiceImp1 implements UserService {...}
// 生產者 2 配置
@Service(weight = 200)
public class UserServiceImp1 implements UserService {...}
// 消費者配置
// @Reference(loadbalance = "roundrobin")
// @Reference(loadbalance = "leastactive")
// @Reference(loadbalance = "consistenthash")
@Reference(loadbalance = "random") // 按權重隨機(預設)
private UserService userService;
叢集容錯
Dubbo 叢集容錯策略:
- Failover Cluster:失敗重試(預設值)。當出現失敗,重試其它伺服器,(預設重試 2 次,使用的是 retries 配置)。一般用於讀操作。
- Failfast Cluster:快速失敗。發起一次呼叫,失敗立即報錯。通常用於寫操作。
- Failsafe Cluster:失敗安全。出現異常時,直接忽略,返回一個空結果。
- Failback Cluster:失敗自動恢復。後臺記錄失敗請求,定時重發。
- **Forking Cluster **:並行呼叫多個伺服器,只要一個成功即返回。
- Broadcast Cluster:廣播呼叫所有提供者,逐個呼叫,任意一臺報錯則報錯。
// 消費者配置
@Reference(cluster = "failover") // 遠端注入
private UserService userService;
服務降級
服務降級:當伺服器壓力劇增的情況下,根據實際業務情況及流量,對一些不太重要的服務(如上圖中的廣告服務和日誌服務)和頁面有策略性地不處理或換種簡單的方式處理,從而釋放伺服器資源以保證核心服務(如上圖中的支付服務)正常運作或高效運作。
Dubbo 服務降級方式:
-
mock = force:return null
:表示消費方對該服務的方法呼叫都直接返回 null 值,不發起遠端呼叫。用來遮蔽不重要服務在不可用時對呼叫方的影響。 -
mock = fail:return null
:表示消費方對該服務的方法呼叫在失敗後,再返回 null 值且不拋異常。用來容忍不重要服務不穩定時對呼叫方的影響。
// 消費者配置
@Reference(mock="force :return null") // 不再呼叫userService的服務
private UserService userService;