高性能RPC框架—----------------------Dubbo一站式快速入门
https://blog.csdn.net/tangyang8941/article/details/88025412
一、Web應用架構的演變
??? ?隨著互聯網的發展,網站應用的規模不斷擴大,Web應用架構也在不斷的演變
??? ?四個階段:單一應用、垂直應用、分布式服務、流動計算
在這里插入圖片描述
1.單一應用架構
??? ?當網站訪問量很小時,只需要一個應用程序,將所有的功能都部署在一起,以減少部署節點和成本
??? ?此時關鍵問題:簡化數據庫操作,數據訪問框架ORM是核心
在這里插入圖片描述
??? ?適用場景:小型網站、管理系統、簡易辦公系統
??? ?局限:
擴展性差
不便于協同開發
不利于升級維護
2. 垂直應用架構
??? ?當訪問量逐漸增大,單一應用(單機)負載太大,此時可以增加服務器來進行負載均衡,提高響應速度,即集群
??? ?但是,當增加的服務器到達一定數據時所帶來的加速度會越來越小,此時單純的增加服務器已無法明顯提升響應速度
??? ?此時,需要將系統業務拆分成多個 互不相關的 系統,分別部署在獨立的服務器上,以提升效率,稱為垂直應用
??? ?此時關鍵問題:加速前端頁面開發MVC框架(MVVM)
在這里插入圖片描述
??? ?優點:通過拆分項目的業務,實現業務上的獨立,降低了開發和維護的難度,便于協同開發,提高了擴展性
??? ?局限:每個垂直模塊中都有相同的內容(entity、dao、service、web),公共資源無法復用,且業務邏輯與界面無法分離
3. 分布式服務架構
??? ?當垂直應用越來越多,應用之間的交互無法避免,有些業務系統無法完全拆分為獨立系統。
??? ?此時,可以將核心業務抽取出現,作為獨立的服務Service,逐漸的形成穩定的服務中心,使前端應用能夠更好的適應市場需要的變化。
??? ?此時關鍵問題:提高業務的利用以及整合分布式服務框架RPC(Remote Procedure Call 遠程過程調用)
在這里插入圖片描述
4. 流動計算架構
??? ?當服務越來越多,服務之間的調用和依賴關系也越來越復雜,誕生了面向服務聽架構體系(SOA: Service-Oriented Architecture )
??? ?容量的評估,小服務資源的浪費等問題開始出現,此時需要增加一個調度中心,基于訪問壓力實時的管理集群容量,提高集群利用率
??? ?此時關鍵問題:資源調度和治理中心,使用dubbo+zookeeper
在這里插入圖片描述
二、RPC簡介
1. RPC是什么
??? ?RPC:Remote Procedure Call 遠程過程調用
是一種進程間的通信方式
它允許應用程序調用網絡上的另一個應用程序中的方法
對于服務的消費者而言,無需了解遠程調用的底層細節,透明的
2. 執行流程
在這里插入圖片描述
??? ?執行流程:
客戶端發起調用請求
客戶端存根 對請求參數(接口、方法、參數等)進行序列化(封裝)
客戶端存根向 服務器存根 發送消息
服務端存根 對接收到的消息 進行反序列化
服務端存根發送請求調用本地方法
服務器執行業務處理
服務器返回處理結果
服務端存根 對處理結果進行序列化
服務端存根 將結果返回給 客戶端存根
客戶端存根 對接收到的結果進行反序列化
客戶端存根 將結果返回給 客戶端
三、Dubbo簡介
1. Dubbo是什么
??? ?Apache Dubbo是一款高性能的Java RPC框架(由阿里巴巴開發,開源貢獻給Apache)
??? ?提供了三個核心功能:
面向接口的遠程方法調用
智能容錯和負載均衡
服務自動注冊和發現
? 參考:官網 http://dubbo.apache.org
2. Dubbo體系結構
在這里插入圖片描述
??? ?執行流程:
Provider:服務的提供者,負責對外提供服務,提供者在啟動的時候,需要向Registry注冊自己能夠提供的服務
Consumer:服務的消費者,消費者在啟動的時候,需要向Registry訂閱自己需要的服務
Registry:注冊中心,授受注冊和訂閱,會異步的通知訂閱者,向消費者提供服務列表
當消費者需要執行遠程過程調用時,會從Registry獲取到服務地址列表(基于負載均衡算法)進行調用,如果調用失敗會重新選擇新的提供者再次調用
Monitor:監控中心,統計服務的調用次數和調用時間,服務消費者和提供者會在內存中累計調用次數和調用時間,定時每分鐘向監控中心發送一次統計數據
? 具體業務流程:
在這里插入圖片描述
四、使用Dubbo
1. Spring版
1.1 創建common工程
??? ?創建entity和service接口
1.2 創建provider工程
??? ?步驟:
添加依賴
<!--依賴于dubbon-common-->
<dependency>
? ? <groupId>com.itany</groupId>
? ? <artifactId>dubbo-common</artifactId>
? ? <version>1.0-SNAPSHOT</version>
</dependency>
<!--spring-->
<dependency>
? ? <groupId>org.springframework</groupId>
? ? <artifactId>spring-core</artifactId>
? ? <version>${springversion}</version>
</dependency>
<dependency>
? ? <groupId>org.springframework</groupId>
? ? <artifactId>spring-beans</artifactId>
? ? <version>${springversion}</version>
</dependency>
<dependency>
? ? <groupId>org.springframework</groupId>
? ? <artifactId>spring-context</artifactId>
? ? <version>${springversion}</version>
</dependency>
<dependency>
? ? <groupId>org.springframework</groupId>
? ? <artifactId>spring-expression</artifactId>
? ? <version>${springversion}</version>
</dependency>
<!--dubbo核心包-->
<dependency>
? ? <groupId>com.alibaba</groupId>
? ? <artifactId>dubbo</artifactId>
? ? <version>2.6.2</version>
</dependency>
<!--使用zookeeper作為注冊中心,在dubbo中會訪問zookeeper-->
<dependency>
? ? <groupId>org.apache.zookeeper</groupId>
? ? <artifactId>zookeeper</artifactId>
? ? <version>3.4.13</version>
</dependency>
<!--zookeeper的客戶端實現-->
<dependency>
? ? <groupId>org.apache.curator</groupId>
? ? <artifactId>curator-framework</artifactId>
? ? <version>4.0.1</version>
</dependency>
編寫實現類
public class UserServiceImpl implements UserService {
? ? @Override
? ? public User findById(int id) {
? ? ? ? System.out.println("UserServiceImpl.findById");
? ? ? ? User user = new User();
? ? ? ? user.setId(id);
? ? ? ? user.setUsername("tom");
? ? ? ? user.setPassword("123");
? ? ? ? return user;
? ? }
}
配置dubbo
<!--配置當前dubbo應用程序的名稱,可自定義,但必須唯一,一般使用項目名-->
<dubbo:application name="dubbo-provider"/>
<!--指定注冊中心地址-->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!--配置dubbo協議和端口(通過該端口來提供服務)-->
<dubbo:protocol name="dubbo" port="8888"/>
<!--指定要暴露的服務接口-->
<dubbo:service interface="com.itany.service.UserService" ref="userService"/>
<bean id="userService" class="com.itany.service.impl.UserServiceImpl"/>
1.3 創建consumer工程
??? ?步驟:
添加依賴
同1.2
編寫使用類
@Controller
public class UserController {
? ? private UserService userService;
? ? public void setUserService(UserService userService) {
? ? ? ? this.userService = userService;
? ? }
? ? public void findUser(){
? ? ? ? User user = userService.findById(1001);
? ? ? ? System.out.println(user);
? ? }
}
}
配置Dubbo
<dubbo:application name="dubbo-consumer"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!--指定要引用的服務-->
<dubbo:reference id="userService" interface="com.itany.service.UserService"/>
<bean class="com.itany.controller.UserController">
? ? <property name="userService" ref="userService" />
</bean>
1.4 測試
啟動zookeeper
編寫并運行provider
public static void main(String[] args) {
? ? ApplicationContext ac=new ClassPathXmlApplicationContext("classpath:provider.xml");
? ? //阻塞線程
? ? new Scanner(System.in).next();
}
編寫并運行consumer
public static void main(String[] args) {
? ? ApplicationContext ac=new ClassPathXmlApplicationContext("classpath:consumer.xml");
? ? UserController userController = ac.getBean(UserController.class);
? ? userController.findUser();
? ? //阻塞線程
? ? new Scanner(System.in).next();
}
2. Spring注解版
2.1 改寫provider
<!--dubbo組件的掃包-->
<dubbo:annotation package="com.itany.service.impl"/>
<!--spring組件的掃包-->
<context:component-scan base-package="com.itany.service.impl"/>
// 方式1
// @Service
// @com.alibaba.dubbo.config.annotation.Service
// 方式2
@Component
@Service
public class UserServiceImpl implements UserService {
2.2 改寫consumer
<dubbo:annotation package="com.itany.controller"/>
<context:component-scan base-package="com.itany.controller"/>
@Controller
public class UserController {
? ? // 使用dubbo的@Reference注入遠程服務對象
? ? @Reference
? ? private UserService userService;
3. SpringBoot版
3.1 創建provider工程
??? ?步驟:
添加依賴
<!--依賴于dubbo-common-->
<dependency>
? ? <groupId>com.itany</groupId>
? ? <artifactId>dubbo-common</artifactId>
? ? <version>1.0-SNAPSHOT</version>
</dependency>
<!--dubbo的starter-->
<dependency>
? ? <groupId>com.alibaba.boot</groupId>
? ? <artifactId>dubbo-spring-boot-starter</artifactId>
? ? <version>0.2.0</version>
</dependency>
編寫實現類
@Component
@Service
public class UserServiceImpl implements UserService {
? ? @Override
? ? public User findById(int id) {
? ? ? ? User user = new User();
? ? ? ? user.setId(id);
? ? ? ? user.setUsername("alice");
? ? ? ? user.setPassword("123");
? ? ? ? return user;
? ? }
}
配置dubbo
server:
? port: 8881
dubbo:
? application:
? ? name: boot-provider
? registry:
? ? address: zookeeper://127.0.0.1:2181
? protocol:
? ? name: dubbo
? ? port: 8888
啟用dubbo
@SpringBootApplication
@EnableDubbo //啟用dubbo
public class BootProviderApplication {
? ? public static void main(String[] args) {
? ? ? ? SpringApplication.run(BootProviderApplication.class, args);
? ? }
}
3.2 創建consumer
??? ?步驟:
添加依賴,同3.1
編寫使用類
@Controller
@RequestMapping("/user")
public class UserController {
? ? @Reference
? ? private UserService userService;
? ? @RequestMapping("/findUser")
? ? public String findUser(int id, Model model) {
? ? ? ? User user = userService.findById(id);
? ? ? ? model.addAttribute("user", user);
? ? ? ? return "success";
? ? }
}
配置dubbo
server:
? port: 8882
dubbo:
? application:
? ? name: boot-consumer
? registry:
? ? address: zookeeper://127.0.0.1:2181
spring:
? thymeleaf:
? ? cache: false
五、配置dubbo
1. 配置的覆蓋關系
??? ?dubbo屬性可以配置在如下六個位置:
消費者引用方法處
提供者暴露方法處
消費者引用接口處
提供者暴露接口處
消費者全局配置處
提供者全局配置處
? 它們的優先順序如下:
方法級優先,接口級次之,全局配置再次之。
如果級別一樣,則消費方優先,提供方次之
? 注:建議由服務提供者設置超時時間
在這里插入圖片描述
2. 常用配置
配置項?? ?作用
timeout?? ?超時時間,單位為毫秒, 默認1000ms
retries?? ?重試次數,不包括第一次調用,默認為2,0表示不重試
check?? ?啟動時檢查提供者是否存在,true表示不存在時報錯,false表示啟動時不檢查,默認為true
url?? ?點對點直連服務提供者,繞過注冊中心,以服務接口為單位
六、監控中心
1. dubbo-admin
??? ?Dubbo的管理控制臺,可以對提供者和消費者進行管理,便于調試,發現問題,解決問題
??? ?下載:GitHub——>搜索dubbo-admin——>選擇master分支——>Download
??? ?配置:修改dubbo-admin目錄下的application.properties文件(指定注冊中心地址)
??? ?打包:mvn package
??? ?運行:java -jar dubbo-admin-0.0.1-SNAPSHOT.jar
??? ?訪問 :http://localhost:7001 默認用戶名和密碼都為root
2. dubbo-monitor-simple
??? ?簡單的監控中心
??? ?配置:修改dubbo-monitor-simple目錄下的dubbo.properties文件(指定注冊中心地址)
??? ?打包:mvn package
??? ?運行:將生成的dubbo-monitor-simple-2.0.0-assembly.tar.gz解壓縮,運行解壓后assembly.bin/start.bat 或 start.sh
??? ?訪問:http://loclahost:8080
??? ?在提供者和消費者中配置,指定監控中心,可以定時每分鐘向監控中心發送一次統計數據
dubbo:
? monitor:
? ? protocol: registry # 配置監控中心,從注冊中心查找監控中心的地址
1
2
3
七、高可用性
??? ?通過對系統進行專門設計,從而減少停機時間,提高系統的高可用性
1. 負載均衡
1.1 簡介
??? ?將接收到的請求按照一定的規則(負載均衡算法)分發到不同的服務器進行處理,從而提高系統響應和處理速度,稱為負載均衡 Load Balance
??? ?Dubbo提供了四種負載均衡策略:
Random LoadBalance 基于權重的隨機負載均衡(默認)
按照權重的比例,隨機選擇集群中的服務器
在這里插入圖片描述
RoundRobin LoadBalance 基于權重的輪循負載均衡
根據權重,按照一定的順序將請求分發給每個服務器(輪流提供服務)
在這里插入圖片描述
LeastActive LoadBalance 最少活躍數的負載均衡
最少活躍調用數,活躍時間(請求的響應時間)較小的服務器會處理更多的請求
在這里插入圖片描述
ConsistentHash LoadBalance 一致性hash的負載均衡
相同參數的請求總是發給同一臺服務器
在這里插入圖片描述
1.2 操作
@Controller
@RequestMapping("/user")
public class UserController {
? ? // 修改負載均衡策略
? ? @Reference(loadbalance = "roundrobin")
? ? private UserService userService;
1
2
3
4
5
6
7
??? ?修改權重的兩種方式:
修改暴露服務時的權重
動態調整權重
2. 服務降級
??? ?當服務器壓力劇增時根據實際業務情況及流量,對一些服務有策略的不處理或換種簡單的方式處理,從而釋放服務器資源以保證核心交易正常運行或高效運行。
??? ?簡單來說,就是將非核心服務進行降級,暫時性的關閉或延遲使用,保證核心服務的正常運行
??? ?Dubbo支持兩種服務降級:
mock=force:return+null
表示消費方對該服務的方法調用都直接返回null,不發起遠程調用
用來屏蔽不重要服務不可用時對調用方的影響
mock=fail:return+null
表示消費方對該服務的方法調用在失敗后,再返回null,不拋出異常
用來容忍不重要服務不穩定時對調用方的影響
八、補充:面試題
1. 高并發的處理
??? ?高并發如何優化?
負載均衡:集群,通過多臺服務器進行負載均衡,提高響應和處理速度
動靜分離:使用Nginx實現,CDN 內容分發網絡
緩存:以空間換時間,提高系統效率
限流:即流量控制,將過量的請求先放到隊列中,等待一定時間后再從隊列中取出處理,類似于地鐵限流
降級:即服務降級
2. 集群環境下session的處理
??? ?幾種解決方式:
Session保持:負載均衡進行請求分發時保證每個客戶端固定的訪問后端的同一臺服務器,如Nginx的ip_hash策略
優點:簡單,不需要對session做任何處理
缺點:無法保證負載絕對均衡
??? ?缺乏容錯性,如果當前訪問的服務器發生故障,用戶被轉移到第二個服務器上,此時他的session信息將失效
Session復制:將每個服務器的Session信息復制到其他服務器節點,保證Session的同步
缺點:如果Session量很大的話可能會造成網絡堵塞,拖慢服務器性能
Session共享:將Session放到一個統一的地方,如可以放到數據庫中,實際中更推薦使用Redis或Memcached。
視頻課程鏈接:Dubbo快速入門視頻課程https://edu.csdn.net/course/detail/10451
在這里插入圖片描述
總結
以上是生活随笔為你收集整理的高性能RPC框架—----------------------Dubbo一站式快速入门的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UNIX再学习 -- 信号
- 下一篇: 最优化学习笔记(九)——基本的共轭方向算