Java微服務(三):負載均衡、序列化、熔斷
本文接著上一篇寫的《Java微服務(二):服務消費者與提供者搭建》,上一篇文章主要講述了消費者與服務者的搭建與簡單的實現。其中重點需要注意配置檔案中的幾個坑。
本章節介紹一些零散的內容:服務的負載均衡,序列化和熔斷
1.服務負載均衡
負載均衡可分為軟體負載均衡和硬體負載均衡。在我們日常開發中,一般很難接觸到硬體負載均衡。但軟體負載均衡還是可以接觸到的,比如 Nginx。dubbo提供的也是軟負載。
詳細內容可以閱讀dubbo官網關於負載均衡的介紹,這裡總結下負載均衡的方式:
- 權重隨機演算法的 RandomLoadBalance
RandomLoadBalance 是加權隨機演算法的具體實現,它的演算法思想很簡單。假設我們有一組伺服器 servers = [A, B, C],他們對應的權重為 weights = [5, 3, 2],權重總和為10。那麼就有5/10的請求達到A伺服器上,3/10和2/10分別達到B和C上。只要隨機數生成器產生的隨機數分佈性很好,在經過多次選擇後,每個伺服器被選中的次數比例接近其權重比例。當呼叫次數比較少時,Random 產生的隨機數可能會比較集中,此時多數請求會落到同一臺伺服器上。
- 最少活躍呼叫數演算法的 LeastActiveLoadBalance
每個服務提供者對應一個活躍數 active。初始情況下,所有服務提供者活躍數均為0。每收到一個請求,活躍數加1,完成請求後則將活躍數減1,在服務執行一段時間後,效能好的服務提供者處理請求的速度更快,因此活躍數下降的也越快,此時這樣的服務提供者能夠優先獲取到新的服務請求、這就是最小活躍數負載均衡演算法的基本思想,目前此演算法還引入了權重值。
- 基於 hash 一致性的 ConsistentHashLoadBalance
首先根據 ip 或者其他的資訊為快取節點生成一個 hash,並將這個 hash 投射到 [0, 232 - 1] 的圓環上。當有查詢或寫入請求時,則為快取項的 key 生成一個 hash 值。然後查詢第一個大於或等於該 hash 值的快取節點,併到這個節點中查詢或寫入快取項。如果當前節點掛了,則在下一次查詢或寫入快取時,為快取項查詢另一個大於其 hash 值的快取節點即可。
- 基於加權輪詢演算法的 RoundRobinLoadBalance
所謂輪詢是指將請求輪流分配給每臺伺服器。舉個例子,我們有三臺伺服器 A、B、C。我們將第一個請求分配給伺服器 A,第二個請求分配給伺服器 B,第三個請求分配給伺服器 C,第四個請求再次分配給伺服器 A。這個過程就叫做輪詢。輪詢是一種無狀態負載均衡演算法,實現簡單,適用於每臺伺服器效能相近的場景下。加權輪詢是將伺服器賦一個權值,然後按照該權值進行輪訓。
程式碼構建,本例使用輪訓演算法做demo
直接在yml配置檔案中新增loadbalance註解就可以
開啟2個服務提供者,並且使用服務消費者消費,檢視日誌
2.序列化
Dubbo 中支援的序列化方式:
- dubbo 序列化:阿里尚未開發成熟的高效 java 序列化實現,阿里不建議在生產環境使用它
- hessian2 序列化:hessian 是一種跨語言的高效二進位制序列化方式。但這裡實際不是原生的 hessian2 序列化,而是阿里修改過的 hessian lite,它是 dubbo RPC 預設啟用的序列化方式
- json 序列化:目前有兩種實現,一種是採用的阿里的 fastjson 庫,另一種是採用 dubbo 中自己實現的簡單 json 庫,但其實現都不是特別成熟,而且 json 這種文字序列化效能一般不如上面兩種二進位制序列化。
- java 序列化:主要是採用 JDK 自帶的 Java 序列化實現,效能很不理想。
dubbo自帶的序列化方式不成熟,而json和java序列化效能不理想。dubbo可以使用hessian2序列化,但是hessian2是跨語言的,沒有單獨對java語言做優化,所以很多單獨給java提供優化的工具效能比hessian2要好。我們為 dubbo 引入 Kryo 和 FST 這兩種高效 Java 序列化實現,來逐步取代 hessian2。
dubbo有關序列化的例項如下:
程式碼構建,首先增加依賴
1 <dependency> 2 <groupId>de.javakaffee</groupId> 3 <artifactId>kryo-serializers</artifactId> 4 <version>0.42</version> 5 </dependency> 6 <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-hystrix --> 7 <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix --> 8 <dependency> 9 <groupId>org.springframework.cloud</groupId> 10 <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> 11 <version>2.0.1.RELEASE</version> 12 </dependency> 13 <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix-dashboard --> 14 <dependency> 15 <groupId>org.springframework.cloud</groupId> 16 <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> 17 <version>2.0.1.RELEASE</version> 18 </dependency>
在配置檔案中增加配置的屬性即可:
此時序列化配置完成,以下總結了常見序列化方式的效能
3.熔斷
由於網路和自身的原因,RPC之間的呼叫並不能保證100%可用,如果伺服器產生了宕機,同時又有大量的請求過來,就會出現雪崩,為了解決此問題,業界提出了熔斷。熔斷器開啟後,為了避免連鎖故障,通過 fallback
方法可以直接返回一個固定值。此時fallback中可以做很多邏輯處理,比喻日誌或者郵件通過開發人員,及時對伺服器進行問題排查,降低風險度。
程式碼構建,首先增加依賴
1 <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-hystrix --> 2 <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix --> 3 <dependency> 4 <groupId>org.springframework.cloud</groupId> 5 <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> 6 <version>2.0.1.RELEASE</version> 7 </dependency> 8 <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix-dashboard --> 9 <dependency> 10 <groupId>org.springframework.cloud</groupId> 11 <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> 12 <version>2.0.1.RELEASE</version> 13 </dependency>
其中第二個依賴是在熔斷儀表盤中使用的。具體程式碼和相關解釋如下如下:
熔斷儀表盤的配置,這裡需要注意spring boot2和1的配置是有區別的,具體可以參考官網文件
1 package com.edu.hello.dubbo.service.user.consumer.config; 2 3 import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet; 4 import org.springframework.boot.web.servlet.ServletRegistrationBean; 5 import org.springframework.context.annotation.Bean; 6 import org.springframework.context.annotation.Configuration; 7 8 /** 9 * @ClassName HystrixDashboardConfiguration 10 * @Deccription TODO 11 * @Author DZ 12 * @Date 2019/9/3 23:10 13 **/ 14 @Configuration 15 public class HystrixDashboardConfiguration { 16 @Bean 17 public ServletRegistrationBean getServlet() { 18 HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet(); 19 ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet); 20 registrationBean.setLoadOnStartup(1); 21 registrationBean.addUrlMappings("/hystrix.stream"); 22 registrationBean.setName("HystrixMetricsStreamServlet"); 23 return registrationBean; 24 } 25 }
啟動服務,檢視結果。這裡只啟動了服務消費者,沒有啟動服務提供者,製造服務超時。
訪問http://localhost:9090/hystrix檢視熔斷介面,其他詳細資訊可以檢視詳細資訊,其中儀表盤的訪問地址是來自於config中,儀表盤如下:
訪問http://localhost:9090/hystrix.stream檢視熔斷儀表盤介面,更加詳細檢視熔斷相關的資訊
儀表盤中相關引數解釋如下:
&n