隨着互聯網的發展,網站應用的規模不斷擴大,Web應用架構也在不斷的演變html
四個階段:單一應用、垂直應用、分佈式服務、流動計算前端
當網站訪問量很小時,只須要一個應用程序,將全部的功能都部署在一塊兒,以減小部署節點和成本java
此時關鍵問題:簡化數據庫操做,數據訪問框架ORM是核心web
適用場景:小型網站、管理系統、簡易辦公系統面試
侷限:算法
當訪問量逐漸增大,單一應用(單機)負載太大,此時能夠增長服務器來進行負載均衡,提升響應速度,即集羣spring
可是,當增長的服務器到達必定數據時所帶來的加速度會愈來愈小,此時單純的增長服務器已沒法明顯提高響應速度數據庫
此時,須要將系統業務拆分紅多個 互不相關的 系統,分別部署在獨立的服務器上,以提高效率,稱爲垂直應用express
此時關鍵問題:加速前端頁面開發MVC框架(MVVM)apache
優勢:經過拆分項目的業務,實現業務上的獨立,下降了開發和維護的難度,便於協同開發,提升了擴展性
侷限:每一個垂直模塊中都有相同的內容(entity、dao、service、web),公共資源沒法複用,且業務邏輯與界面沒法分離
當垂直應用愈來愈多,應用之間的交互沒法避免,有些業務系統沒法徹底拆分爲獨立系統。
此時,能夠將核心業務抽取出現,做爲獨立的服務Service,逐漸的造成穩定的服務中心,使前端應用可以更好的適應市場須要的變化。
此時關鍵問題:提升業務的利用以及整合分佈式服務框架RPC(Remote Procedure Call 遠程過程調用)
當服務愈來愈多,服務之間的調用和依賴關係也愈來愈複雜,誕生了面向服務聽架構體系(SOA: Service-Oriented Architecture )
容量的評估,小服務資源的浪費等問題開始出現,此時須要增長一個調度中心,基於訪問壓力實時的管理集羣容量,提升集羣利用率
此時關鍵問題:資源調度和治理中心,使用dubbo+zookeeper
RPC:Remote Procedure Call 遠程過程調用
執行流程:
Apache Dubbo是一款高性能的Java RPC框架(由阿里巴巴開發,開源貢獻給Apache)
提供了三個核心功能:
參考:官網 http://dubbo.apache.org
執行流程:
具體業務流程:
建立entity和service接口
步驟:
添加依賴
<!--依賴於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.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>
啓動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(); }
<!--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 {
<dubbo:annotation package="com.itany.controller"/> <context:component-scan base-package="com.itany.controller"/>
@Controller public class UserController { // 使用dubbo的@Reference注入遠程服務對象 @Reference private UserService userService;
步驟:
添加依賴
<!--依賴於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.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屬性能夠配置在以下六個位置:
它們的優先順序以下:
注:建議由服務提供者設置超時時間
配置項 | 做用 |
---|---|
timeout | 超時時間,單位爲毫秒, 默認1000ms |
retries | 重試次數,不包括第一次調用,默認爲2,0表示不重試 |
check | 啓動時檢查提供者是否存在,true表示不存在時報錯,false表示啓動時不檢查,默認爲true |
url | 點對點直連服務提供者,繞過註冊中心,以服務接口爲單位 |
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
簡單的監控中心
配置:修改dubbo-monitor-simple目錄下的dubbo.properties文件(指定註冊中心地址)
打包:mvn package
運行:將生成的dubbo-monitor-simple-2.0.0-assembly.tar.gz解壓縮,運行解壓後assembly.bin/start.bat 或 start.sh
在提供者和消費者中配置,指定監控中心,能夠定時每分鐘向監控中心發送一次統計數據
dubbo: monitor: protocol: registry # 配置監控中心,從註冊中心查找監控中心的地址
經過對系統進行專門設計,從而減小停機時間,提升系統的高可用性
將接收到的請求按照必定的規則(負載均衡算法)分發到不一樣的服務器進行處理,從而提升系統響應和處理速度,稱爲負載均衡 Load Balance
Dubbo提供了四種負載均衡策略:
Random LoadBalance 基於權重的隨機負載均衡(默認)
按照權重的比例,隨機選擇集羣中的服務器
RoundRobin LoadBalance 基於權重的輪循負載均衡
根據權重,按照必定的順序將請求分發給每一個服務器(輪流提供服務)
LeastActive LoadBalance 最少活躍數的負載均衡
最少活躍調用數,活躍時間(請求的響應時間)較小的服務器會處理更多的請求
ConsistentHash LoadBalance 一致性hash的負載均衡
相同參數的請求老是發給同一臺服務器
@Controller @RequestMapping("/user") public class UserController { // 修改負載均衡策略 @Reference(loadbalance = "roundrobin") private UserService userService;
修改權重的兩種方式:
當服務器壓力劇增時根據實際業務狀況及流量,對一些服務有策略的不處理或換種簡單的方式處理,從而釋放服務器資源以保證核心交易正常運行或高效運行。
簡單來講,就是將非核心服務進行降級,暫時性的關閉或延遲使用,保證核心服務的正常運行
Dubbo支持兩種服務降級:
mock=force:return+null
表示消費方對該服務的方法調用都直接返回null,不發起遠程調用
用來屏蔽不重要服務不可用時對調用方的影響
mock=fail:return+null
表示消費方對該服務的方法調用在失敗後,再返回null,不拋出異常
用來容忍不重要服務不穩定時對調用方的影響
高併發如何優化?
幾種解決方式:
Session保持:負載均衡進行請求分發時保證每一個客戶端固定的訪問後端的同一臺服務器,如Nginx的ip_hash策略
優勢:簡單,不須要對session作任何處理
缺點:沒法保證負載絕對均衡
缺少容錯性,若是當前訪問的服務器發生故障,用戶被轉移到第二個服務器上,此時他的session信息將失效
Session複製:將每一個服務器的Session信息複製到其餘服務器節點,保證Session的同步
缺點:若是Session量很大的話可能會形成網絡堵塞,拖慢服務器性能
視頻課程連接:Dubbo快速入門視頻課程(通俗易懂)http://edu.51cto.com/course/16189.html