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