搭載Dubbo+Zookeeper踩了這麼多坑,我終於決定寫下這篇!
大家好,我是melo,一名大二上軟件工程在讀生,經歷了一年的摸滾,現在已經在工作室裡邊準備開發後台項目啦。
這篇文章我們不談數據結構了,來談談入門分佈式踩過的坑。感覺到了分佈式這一層,由於技術更新迭代很快,我們似乎很難接觸到第一手材料了(就連官方文檔都沒有實時更新,很多不適用)。幾經摸索,看視頻,翻文檔,找博客,終於把Dubbo+zookeeper的小demo給成功跑起來了,寫下這篇是因為裡邊有好多的坑,具體我都寫在代碼的注釋裡邊了,希望可以幫到更多小夥伴,少踩一點坑,專心搞技術!
大型互聯網項目架構目標
衡量網站的性能指標:
•響應時間:指執行一個請求從開始到最後收到響應數據所花費的總體時間。
•並發數:指系統同時能處理的請求數量。
•並發連接數:指的是客戶端向服務器發起請求,並建立了TCP連接。每秒鐘服務器連接的總TCP數量
•請求數:也稱為QPS(Query Per Second) 指每秒多少請求.
•並發用戶數:單位時間內有多少用戶
•吞吐量:指單位時間內系統能處理的請求數量。
•QPS:Query Per Second 每秒查詢數。
•TPS:Transactions Per Second 每秒事務數。
•一個事務是指一個客戶機向服務器發送請求然後服務器做出反應的過程。客戶機在發送請求時開始計時,收到服務器響應後結束計時,以此來計算使用的時間和完成的事務個數。
•一個頁面的一次訪問,只會形成一個TPS;但一次頁面請求,可能產生多次對服務器的請求,就會有多個QPS
集群和分佈式
傳統
- 集群: 很多人干同一件事情
很多台服務器,上邊負責同一個模塊
- 分佈式 : 很多人干不同的事情,合起來是一件大事情
很多台服務器,上邊負責不同的小模塊,最後合成一個大模塊
- 集群和分佈式,往往是同時存在的
高可用性
- 一個服務器掛了,不會影響另一個服務器,可以保證服務一直處於可用狀態
高伸縮性
- 由於把各個模塊盡量抽離開了,降低了彼此之前的耦合關係,所以比如要給E模塊加多幾個,可用直接加不會影響其他模塊
高可擴展性
- 類似開閉原則,因為耦合度不高,所以擴展起來不是很難
架構演變
假設項目由 ABCD基礎模塊組成 E是公共模塊
單體架構
- 一個服務器上,放着一整個項目 ABCDE
垂直架構
- 把項目拆成獨立(互相沒有關聯)的兩個模塊 如 AB CD , 此時的E呢,因為兩個服務器沒有關聯,所以E就不得不部署多次.即 ABE CDE 兩台服務器
缺點
- 公共模塊在每個服務器上都需要用到
分佈式架構
- 垂直架構看起來已經是 不同服務器干不同的事情了, 不過還有一個公共模塊E,在兩個服務器中都出現過,我們要優化的話,可以多加一台服務器,單獨放E
遠程調用E(RPC)
- 用到 HTTP REST風格等(Dubbo都幫我們封裝好了)
缺點
- E一但發生了改變,所有調用他的地方都需要去改變
SOA架構
沒有什麼是再多加一層解決不了的,加一個中間商ESB
微服務架構(待深入)
Dubbo的架構
節點角色說明:
•Provider暴露服務的服務提供方
•Container:服務運行容器
•Consumer:調用遠程服務的服務消費方
•Registry:服務註冊與發現的註冊中心
•Monitor:統計服務的調用次數和調用時間的監控中心
快速入門
Zookeeper下載
官網://zookeeper.apache.org/releases.html
我選擇的是這個版本,帶有bin目錄的
Windows
- 直接解壓出來
- 將conf目錄下的zoo_sample.cfg複製一份,改名為zoo.cfg(因為默認配置文件是這個名字)
- 然後退回安裝目錄,新建一個空的data 和 log
4 . 進入conf中修改zoo.cfg配置文件,將dataDir=/tmp/zookeeper 修改成 zookeeper 安裝目錄所在的 data 文件夾,再添加一條添加數據日誌的配置(需要根據自己的安裝路徑修改)。
5 . 雙擊 bin目錄下的 zkServer.cmd 啟動程序:
6 . 控制台顯示 bind to port 0.0.0.0/0.0.0.0:2181,表示服務端啟動成功!
7 . 雙擊同目錄下的zkCli.cmd 啟動客戶端
出現 Welcome to Zookeeper!,表示我們成功啟動客戶端。
注意
當需要一直啟動zookeeper時,這兩個cmd不能關掉不能關掉不能關掉!!!!!!!要保持運行
Linux
tar -zxvf (你下載的壓縮包名稱)
cd (你的安裝目錄)
cd conf/
cp zoo_sample.cfg zoo.cfg
vimzoo.cfg
此處需要按照上邊一樣修改,注意需要根據自己的安裝路徑修改 , 同樣也得創建data和log,修改端口等
cd ..
cd bin/
sh zkServer.sh start
sh zkCli.sh
- 如果下載的版本不一樣,可能需要自行查看一下幫助命令
詳細配置(SpringBoot)
多模塊開發
此處其實用到了三個模塊,一個是公共接口模塊,一個是provider模塊,一個是consumer模塊
其中後兩個都共同去依賴公共模塊
而provider又依賴consumer模塊
想要完整源碼的話可以評論區聯繫一下博主
特別注意
我們兩個模塊都要去@import com.example.dubbo_interface.service.StuService;
- 那這裡就意味着什麼,別的項目得能找到這個包啊,要怎麼把公共接口dubbo_interface裡邊的包暴露出來,可供別人調用呢,這裡是用到了maven的install命令,把dubbo_interface這一模塊打包到公共倉庫去了,這樣別的項目就可以引用裡邊的內容了!
如果對maven這一塊還不太熟悉的話,具體可以參照這篇 maven(先給自己挖個坑,整理好了會發出來的)
以下一切配置都完成了之後,記得先打開zookeeper!打開zookeeper!打開zookeeper!
provider提供服務端
yml文件
dubbo:
application:
#配置應用的名稱(應用可以是提供者也可以是消費者)
name: dubbo_service
#協議中心
protocol:
#固定的, 是只有provider才需要嗎?
name: dubbo
port: 20882
#指定註冊中心的位置,127.0.0.1是ip地址,2181是端口號
registry:
address: zookeeper://127.0.0.1:2181
######這裡是關鍵,很多教程沒有配置,導致zookeeper連接不上
timeout: 50000
#要暴露的服務所在的包(配置掃包)
#也可以在註解那裡掃包
# scan:
# base-packages: com.example.dubbo_service.service
#指定該項目模塊啟動的端口,不可與其他項目端口重複
server:
port: 8081
具體Service服務端
package com.example.dubbo_service.service;
import com.example.dubbo_interface.service.StuService;
import org.apache.dubbo.config.annotation.DubboService;
//暴露服務
@DubboService
public class StuServiceImpl implements StuService {
@Override
public String login() {
return "111";
}
}
引入Dubbo依賴和控制zookeeper的客戶端
這裡使用的是2.7.8版本,搭配2.5.5版本的Springboot
注意依賴接口模塊
<!--依賴接口項目-->
<dependency>
<groupId>com.example</groupId>
<artifactId>dubbo_interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- Dubbo Spring Boot Starter -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.8</version>
</dependency>
<!--curator依賴-->
<!--Curator提供了一套Java類庫, 可以更容易的使用ZooKeeper。 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.1.0</version>
</dependency>
啟動類
@EnableDubbo註解一般寫在啟動類上,默認會掃描當前註解所在類的包路徑下的所有@Dubboservice標註的組件,如果需要自定義掃描註冊的bean(服務實現),可以使用@DubboComponentScan或掃描屬性實現。另外,@EnableDubbo註解等效於在配置文件中使用dubbo.scan.base-packages一步到位(開啟dubbo功能+掃描dubbo的服務實現bean)
package com.example.dubbo_service;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//開啟基於註解的Dubbo功能,同時掃描要暴露的服務端所在的位置
@EnableDubbo(scanBasePackages = "com.example.dubbo_service.service")
@SpringBootApplication
public class DubboServiceApplication {
public static void main(String[] args) {
SpringApplication.run(DubboServiceApplication.class, args);
}
}
consumer消費者端
注意,其不同於傳統的service,這裡為了能獨立啟動,也要設置成web項目那種(再藉助Springboot啟動)
yml文件
dubbo:
application:
#指定當前服務/應用的名字(同樣的服務名字相同,不要和別的服務同名)
name: dubbo_controller
## consumer不需要這個通信協議,因為consumer無需通過Dubbo來遠程調用
# protocol:
# name: dubbo
## port: 20881
#指定註冊中心的位置,127.0.0.1是ip地址,2181是端口號
registry:
address: zookeeper://127.0.0.1:2181
######這裡是關鍵,很多教程沒有配置,導致zookeeper連接不上
timeout: 50000
##發現按照官網只配consumer的話,也還是連不到zookeeper的
consumer:
##後來發現這裡就等效於DubboReference註解那裡的timeout設置
timeout: 3000
##此處是用在暴露掃包的,consumer不需要暴露服務
# scan:
# base-packages: com.example.dubbo_service.service
#指定該項目模塊啟動的端口,不可與其他項目端口重複
server:
port: 8082
具體Controller消費者端
package com.example.dubbo_controller.controller;
import com.example.dubbo_interface.service.StuService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/stu")
public class StuController {
/**
* 遠程注入
* 從zookeeper註冊中心獲取該service的訪問url
* 進行遠程調用RPC
* 將結果封裝成一個代理對象,給變量賦值
*/
//沒timeout好像就出問題了??連不上??
//也可以在yml裡邊的consumer的timeout進行配置
@DubboReference/*(timeout = 5000)*/
StuService stuService;
@RequestMapping("/login")
public String login(){
return stuService.login();
}
}
同上引入依賴
<!--依賴接口項目-->
<dependency>
<groupId>com.example</groupId>
<artifactId>dubbo_interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- Dubbo Spring Boot Starter -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.8</version>
</dependency>
<!--curator依賴-->
<!--Curator提供了一套Java類庫, 可以更容易的使用ZooKeeper。 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.1.0</version>
</dependency>
啟動類
package com.example.dubbo_controller;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//開啟基於Dubbo的註解
@EnableDubbo
@SpringBootApplication
public class DubboControllerApplication {
public static void main(String[] args) {
SpringApplication.run(DubboControllerApplication.class, args);
}
}
公共接口
因為provider和consumer兩個模塊都會需要用到這個接口,所以不如抽取出來作為公共的接口
package com.example.dubbo_interface.service;
//公共接口
public interface StuService {
String login();
}
Dubbo-admin
人生建議: 直接用老版本的前後端未分離,直接可以一鍵啟動使用,端口默認在本機的7001
關於老版本的dubbo-admin我是直接用的尚硅谷教程裡邊的的尚硅谷的文件裡邊應該會有,如果找不着的話也可以評論留言一下
修改application.properties
server.port
該項目要啟動的端口
registry.address
要監測的註冊中心的地址
啟動之前要先啟動zookeeper!!!(如何啟動參照上邊zookeeper安裝)
訪問localhost:端口號
默認用戶名和密碼都是root
最終效果
先開着zookeeper,如何啟動service模塊,再啟動controller模塊,最後啟動dubbo-admin項目
可以看到有一個服務數,兩個應用數,一個是提供者,一個是消費者
服務是我們的接口模塊
提供者
消費者
訪問我們的接口
完整工程代碼
- 這裡三個模塊的互相依賴關係pom文件,基於個人項目名稱不同而有所不同,若對於pom文件和依賴關係還有點迷惑的小夥伴們歡迎評論區微信交流
寫在最後
- 分佈式這一塊還是剛剛入門,原理方面希望也能多了解了解,希望接下來還能繼續堅持下去,多多補充這一塊的知識。關於Dubbo的一些高級特性,以及zookeeper的具體學習,過段時間再來補充!(flag瘋狂立起來了)
PPT來源
- 黑馬Dubbo教程
- dubbo-admin文件來源: 尚硅谷