Dubbo
- 注意
當啟動服務時,該服務會佔用本機一個埠號,故在一臺電腦啟動多個服務時需要在配置檔案中更佔用本機的埠號
<!--服務佔用本機的埠-當本機啟動多個服務時須保持不同-->
<dubbo:protocol port=""/>
<!--dubbo的配置-->
<!--1.配置專案的名稱,唯一-->
<dubbo:application name="dubbo-service"/>
<!--2.配置註冊中心的地址-->
<dubbo:registry address="zookeeper://192.168.23.129:2181" timeout="250000"/>
<!--3.配置dubbo包掃描,註解註冊服務-->
<!-- <dubbo:annotation package="com.yh1.impl" />-->
<!--3.2xml配置方式註冊服務,類上不需要註解-->
<dubbo:service interface="com.yh.ours.UserService" ref="demoService"/>
<bean id="demoService" class="com.yh1.impl.UserServiceImpl"/>
序列化
查詢出資料後返回給消費者時所執行的便是序列化
- 作用:用於不同機器間傳輸物件的轉換,將物件序列化為 流資料進行傳輸
- 被序列化的物件類必須實現序列化介面Serializable
- 接受到流資料後,反序列化為java物件
- 序列化和反序列化兩者皆需要用到物件類,故定義在一個獨立模組中,讓兩者依賴它—>類似於公共介面模組
- 即domain/pojo實體類皆需要實現介面Serializable且放在獨立模組來作為資源被依賴
<groupId>org.yh</groupId>
<artifactId>debbo-interface</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--被依賴資源-->
<dependency>
<groupId>org.yh</groupId>
<artifactId>dubbo-pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
序列化和反序列化操作dubbo已經封裝好,只需讓pojo類實現介面即可
eg:
//必須實現Serializable
//一個實體類用於 模仿序列化和反序列化操作
public class User implements Serializable {
int id;
String name;
public User() {
}
public User(int id, String name) {
this.id = id;
this.name = name;
}
//省略get和set方法
Cotroller程式碼
@RequestMapping("/find.do")
public User find(int id){
return userService.findById(id);
}
地址快取
問:註冊中心掛了,服務是否可以正常訪問?
答:可以,當第一次訪問後,會將服務地址快取至本地
但是當服務的地址變了以後就不行了,需要重新訪問註冊中心獲取
超時和重試
超時
問:消費者建立執行緒呼叫提供者服務,如果呼叫失敗或者提供者查詢時間過長或掛了,則消費者將一直等待
- 可以在服務者方法中使用執行緒沉睡來模擬上述情況
@Service
public class UserServiceImpl implements UserService {
@Override
public User findById(int id) {
//此處讓服務睡5秒,用來演示超時操作
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
User user=new User(1,"jack");
return user;
}
}
解決:設定timeout屬性值來控制超時時間
- 在消費方@reference註解中設定
- 在提供者@service註解中設定
- 在配置檔案中配置
<!--2.配置註冊中心的地址-->
<dubbo:registry address="zookeeper://192.168.23.129:2181" timeout="250000"/>
- 建議配置在服務提供方@Service上
- 超時時消費者報錯如下
重試
問題:出現了網路抖動網突然斷了一下,斷了3s超時時間設定是1s,則這一次請求就會失敗,則會重新傳送請求,一共傳送3次
解決1:通過retries屬性類設定重試次數。預設為2
多版本
灰度釋出:新功能時,讓一部分使用者使用新版本,穩定後讓全部使用者使用新的版本。
使用:使用version屬性來設定和呼叫同一個介面的不同版本
eg:公共介面模組中的UserService介面在服務提供者中有倆實現類UserServiceImpl1和UserServiceImpl2
在服務提供者的UserServiceImpl1@Service(version=“v1.0”)中設定version和UserServiceImpl2@Service(version=“v2.0”)
在消費者的@Reference(version=“v1.0 or v2.0”)中設定version來選擇使用哪個版本
注:此處檢驗失敗,原因未知
負載均衡
適用於叢集環境,相同的服務部署在多臺機器上
模擬步驟:
1.在服務提供者的@Service註解中新增weight屬性,配置權重(可在服務內列印一句話來區別不同的服務)
2.啟動該服務tomcat7:run
3.更改三個埠號後繼續1,2,3步驟,直至啟動三個伺服器為止,保持權重不同
4.在消費者的@reference註解中配置loadbalance屬性(共有四個值下面有)
5.啟動服務,開始模擬
- 負載均衡策略(4種):來解決訪問哪個機器
可以更改同一個服務的tomcat,dubbo的qos,本機三個的埠來模擬同一服務部署在多臺機器
1.
<!--tomcat外掛-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>8000</port>
<path>/</path>
</configuration>
</plugin>
2.
<dubbo:protocol port="20881"/>
3.
<!--dubbo的配置-->
<!--1.配置專案的名稱,唯一-->
<dubbo:application name="dubbo-service">
<!--dubbo的pos服務一個服務會啟動一次,故一臺機器時不同服務需要更改-->
<dubbo:parameter key="qos.port" value="33331"/>
</dubbo:application>
- 權重weight是服務提供者@Service註解的配置屬性
- Random按權重weight屬性隨機。按權重設定隨機概率
- RoundRobin按權重輪詢
- LeastActice最少活躍呼叫數,相同則隨機–>使用機器中處理請求最快的的機器
- ConsisitentHash:一致性Hash,相同引數的請求總是發到同一提供者
- 在消費者的@Reference註解中使用loadbalance屬性(該屬性值為loadbalance抽象類的四種實現類屬性即上的小寫)來設定採用上述哪種負載均衡策略
叢集容錯
問題: 消費者呼叫叢集中某一機器出錯了,該如何處理?
- 叢集容錯模式:
- **Failover Cluster:**失敗重試。預設值。當出現失敗,重試其它伺服器,預設重試2次,使用retries配置。–一般用於讀操作
- **Failfast Cluster ?*快速失敗,發起-次呼叫,失敗立即報錯。–通常用於寫操作。
- **Failsafe Cluster:**失敗安全,出現異常時,直接忽略。返回一個空結果。–用於寫一些不重要的日誌結果
- **Failback Cluster:**失敗自動恢復,後臺記錄失敗請求,定時重發。
- **Forking Cluster ?*並行呼叫多個伺服器,只要一個成功即返回。–耗效能
- Broadcast Cluster: 廣播呼叫所有提供者,逐個呼叫,任意一臺報錯則報錯。–同步要求較高時使用,如同時更新三個機器上的資料
- 在消費者的@Reference註解中使用cluster屬性(該屬性值為cluster抽象類的四種實現類屬性即上的小寫)來設定採用上述哪種叢集容錯策略
服務降級
場景描述:
- 當伺服器壓力劇增的情況下,根據實際業務情況及流量,對一些服務和頁面有策略的不處理或換種簡單的方式處理,從而釋放伺服器資源以保證核心交易正常運作或高效運作
- 服務降級方式:
-
mock= force:return null:表示消費方對該服務的方法呼叫都直接返回null值,不發起遠端呼叫。用來遮蔽不重要服務不可用時對呼叫方的影響。
-
mock=fail:return null:表示消費方對該服務的方法呼叫在失敗後,再返回null值,不拋異常。用來容忍不重要服務不穩定時對呼叫方的影響
- 只需在消費方配置
@Reference(mock =“ force :return null")
private UserService userService;