dubbo特性
文章目錄
- 基本使用
- 參數校驗
- pom
- 使用場景與實例
- 參數標注示例
- 參數驗證示例
- 開啟驗證
- 多版本控制version
- 提供者
- 消費者
- 負載均衡
- 服務分組
- 提供者
- 消費者
- 服務超時
- 服務重試
- 集群容錯
- 服務降級
- 異步調用
- 定義 CompletableFuture 簽名的接口
- 測試
- 啟動時檢查
- 診斷與調優
- 優雅停機
- 調用結果緩存
- 注冊信息 簡化
- 提供者
- 消費者
- 注意
- 并發控制
- 連接控制
- 服務端連接控制
- 客戶端連接控制
- 粘滯連接
- 線程模型
- 配置注冊服務
- 協議
- dubbo
- Triple
- 其他
- 配置中心
- 應用級服務發現
- 延遲暴露
- 問題
- 線程池資源枯竭
基本使用
參數校驗
pom
<dependency><groupId>javax.validation</groupId><artifactId>validation-api</artifactId><version>1.0.0.GA</version> </dependency> <dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>4.2.0.Final</version> </dependency>使用場景與實例
服務端在向外提供接口服務時,解決各種接口參數校驗問題
參數標注示例
import java.io.Serializable; import java.util.Date;import javax.validation.constraints.Future; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Past; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size;public class ValidationParameter implements Serializable {private static final long serialVersionUID = 7158911668568000392L;@NotNull // 不允許為空@Size(min = 1, max = 20) // 長度或大小范圍private String name;@NotNull(groups = ValidationService.Save.class) // 保存時不允許為空,更新時允許為空 ,表示不更新該字段@Pattern(regexp = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$")private String email;@Min(18) // 最小值@Max(100) // 最大值private int age;@Past // 必須為一個過去的時間private Date loginDate;@Future // 必須為一個未來的時間private Date expiryDate;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Date getLoginDate() {return loginDate;}public void setLoginDate(Date loginDate) {this.loginDate = loginDate;}public Date getExpiryDate() {return expiryDate;}public void setExpiryDate(Date expiryDate) {this.expiryDate = expiryDate;} }參數驗證示例
import javax.validation.constraints.Min; import javax.validation.constraints.NotNull;public interface ValidationService {void save(@NotNull ValidationParameter parameter); // 驗證參數不為空void delete(@Min(1) int id); // 直接對基本類型參數驗證 }開啟驗證
在客戶端驗證參數
@DubboReference(methods = {},validation = "true") private GoodsService goodsService;在服務器端驗證參數
@DubboService(validation = "true") public class GoodsServiceImpl implements GoodsService { }多版本控制version
提供者
@DubboService(version = "v1.0") public class GoodsServiceImpl implements GoodsService {}消費者
@DubboReference(version = "v1.0") private GoodsService goodsService;負載均衡
注解配置
@DubboService(loadbalance = "roundrobin",methods = {}) public class GoodsServiceImpl implements GoodsService {}@DubboReference(loadbalance = "roundrobin",methods = {}) private GoodsService goodsService;服務分組
使用場景
當一個接口有多種實現時,可以用 group 區分
提供者
使用 @DubboService 注解,添加 group 參數
@DubboService(group = "demo") public class DemoServiceImpl implements DemoService {... }@DubboService(group = "demo2") public class Demo2ServiceImpl implements DemoService {... }消費者
使用 @DubboReference 注解,添加 group 參數
@DubboReference(group = "demo") private DemoService demoService;@DubboReference(group = "demo2") private DemoService demoService2;// group值為 *----> 標識 匹配任意服務分組 @DubboReference(group = "*") private DemoService demoService2;服務超時
超時后,進行重試,也就是接下來的容錯—> 設為 1 s
// 還可以進行方法級別的 超時設置 // 誰定義 服務就大概知道什么情況,建議 設置在服務提供方 @DubboService(version = "v1.0",timeout = 1000) public class GoodsServiceImpl implements GoodsService {}服務重試
- 設置超時時間,在這個時間段內,無法完成訪問,自動斷開連接
- 如果出現網絡抖動,則這一次請求就會失敗
- Dubbo提供重試機制避免類似問題發生
- 通過retries 屬性設置重試次數,默認為 2次
集群容錯
Failover Cluster
失敗自動切換,當出現失敗,重試其它服務器。通常用于讀操作,但重試會帶來更長延遲。
可通過 retries="2" 來設置重試次數(不含第一次)。
重試次數配置如下:
@DubboReference(version = "v1.0",methods = {},cluster="failover") private GoodsService goodsService;服務降級
服務降級是—>指服務在非正常情況下進行降級應急處理,一般配合容錯
使用場景
使用方式
@DubboReference(version = "v1.0", methods = {}, retries = 2, mock = "force:return null") private GoodsService goodsService;異步調用
定義 CompletableFuture 簽名的接口
服務接口定義
public interface AsyncService {CompletableFuture<String> sayHello(String name); }服務實現
import org.apache.dubbo.config.annotation.DubboService;import java.util.concurrent.CompletableFuture;@DubboService(version = "v1.0", timeout = 500000) public class AsyncServiceImpl implements AsyncService {// 還可以整合線程池!!!@Overridepublic CompletableFuture<String> sayHello(String name) {return CompletableFuture.supplyAsync(() -> {System.out.println(name);try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}//返回值為String,與定義時相同!return "async response from provider.";});} }測試
import org.apache.dubbo.config.annotation.DubboReference; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException;@RestController public class TestBean {@DubboReference(version = "v1.0")private AsyncService asyncService;@GetMapping("/test")public String test() throws InterruptedException, ExecutionException {CompletableFuture<String> str = asyncService.sayHello("xiaoding");return "success";}}訪問 秒相應!!!
啟動時檢查
Dubbo 缺省會在啟動時檢查依賴的服務是否可用,** 不可用時 會拋出異常,阻止 Spring 初始化完成**
好處:以便上線時,能及早發現問題,默認 check="true"
可以通過 check="false" 關閉檢查,比如,測試時,有些服務不關心,或者出現了循環依賴,必須有一方先啟動
// 推薦設置為false! @DubboReference(check = false) private GoodsService goodsService;check----->只用來 啟動時檢查,運行時沒有相應的依賴仍然會報錯!!!
診斷與調優
優雅停機
設置優雅停機超時時間,缺省超時時間是 10 秒,如果超時則強制關閉。 該參數可在 dubbo.properties 文件里配置例如:配置為 30 秒
dubbo:application:name: dubbo-provider #dubbo提供者名稱shutwait: 30調用結果緩存
緩存類型
lru 基于最近最少使用原則刪除多余緩存,保持最熱的數據被緩存。
threadlocal 當前線程緩存,比如一個頁面渲染,用到很多 portal,每個 portal 都要去查用戶信息,通過線程緩存,可以減少這種多余訪問。
使用場景
結果緩存,用于加速熱門數據的訪問速度,Dubbo 提供聲明式緩存,以減少用戶加緩存的工作量
使用方式:可以指定方法或類進行緩存
@DubboReference(cache = "lru",methods = {}) private GoodsService goodsService;注冊信息 簡化
背景
服務為維度注冊進入注冊中心,導致了數據量的膨脹,進而引發注冊中心 (如 zookeeper) 的網絡開銷增大,性能降低
使用場景
數據量大導致注冊中心的網絡開銷增大,性能降低,減少注冊中心上服務的注冊數據
使用方式: 用 Spring-Bean 配置zk,yaml中 不需要配置!
提供者
import org.apache.dubbo.config.RegistryConfig; import org.apache.dubbo.config.annotation.DubboService; import org.springframework.context.annotation.Bean;public class DubboConfig {@Beanpublic RegistryConfig registryConfig() {RegistryConfig registryConfig = new RegistryConfig();registryConfig.setAddress("zookeeper://127.0.0.1:2181");registryConfig.setSimplified(true);registryConfig.setExtraKeys("retries,owner");return registryConfig;}}class Service {// 暴露服務@DubboService(version = "1.1.8", group = "d-test", executes = 4500, retries = 7, owner = "victanno", timeout = 5300)public class AnnotationServiceImpl implements AnnotationService {public String sayHello(String name) {System.out.println("async provider received: " + name);return "annotation: hello, " + name;}} }消費者
import org.apache.dubbo.config.RegistryConfig; import org.apache.dubbo.config.annotation.DubboReference;import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component;public class DubboConfig {@Beanpublic RegistryConfig registryConfig() {RegistryConfig registryConfig = new RegistryConfig();registryConfig.setAddress("zookeeper://127.0.0.1:2181");registryConfig.setSimplified(true);return registryConfig;}}@Component("annotationAction") public class AnnotationAction {@DubboReference(version = "1.1.8", group = "d-test", owner = "vvvanno", retries = 4, actives = 6, timeout = 4500)private AnnotationService annotationService;public String doSayHello(String name) {return annotationService.sayHello(name);} }注意
如果一個應用中既有 provider 又有 consumer,那么配置需要合并成:
@Bean //注冊中心配置 public RegistryConfig registryConfig() {RegistryConfig registryConfig = new RegistryConfig();registryConfig.setAddress("zookeeper://127.0.0.1:2181");registryConfig.setSimplified(true);//只對provider生效registryConfig.setExtraKeys("retries,owner");return registryConfig; }并發控制
服務器端并發執行(或占用線程池線程數)不能超過 10 個
@DubboService(loadbalance = "roundrobin",executes = 10)客戶端并發執行(或占用連接的請求數)不能超過 10 個
@DubboReference(actives=10,methods = {}) private GoodsService goodsService;連接控制
Dubbo 中服務端和客戶端的連接控制
服務端連接控制
限制服務器端接受的連接不能超過 10 個
dubbo:application:name: dubbo-provider # 注冊的服務名registry:address: zookeeper://192.168.111.101:2181 # 注冊地址 使用zookeeperprotocol:name: dubbo # dubbo協議port: -1accepts: 10 # 連接控制客戶端連接控制
限制客戶端 服務使用連接不能超過 10 個
@DubboReference(connections = 10) private GoodsService goodsService;粘滯連接
使用場景
粘滯連接 用于 有狀態服務,盡可能讓客戶端總是向同一提供者發起調用,除非該提供者掛了,再連另一臺
粘滯連接將自動開啟 延遲連接,以減少長連接數
使用方式:類或方法級別
@DubboReference(sticky = true, methods = {}) private GoodsService goodsService;線程模型
如何調整線程模型
在protocol下配置dispatcher: all
dubbo:application:name: dubbo-springboot-demo-providerprotocol:name: dubboport: -1#配置線程模型dispatcher: allregistry:id: zk-registryaddress: zookeeper://127.0.0.1:2181config-center:address: zookeeper://127.0.0.1:2181metadata-report:address: zookeeper://127.0.0.1:2181各線程模型的配置值:
配置注冊服務
使用 Java Config 代替注解
注意: Java Config 是 DubboService 或 DubboReference 的替代方式,對于有復雜配置需求的服務建議使用這種方式
@Configuration public class ProviderConfiguration {@Beanpublic ServiceConfig demoService() {ServiceConfig service = new ServiceConfig();service.setInterface(DemoService.class);service.setRef(new DemoServiceImpl());service.setGroup("dev");service.setVersion("1.0.0");Map<String, String> parameters = new HashMap<>();service.setParameters(parameters);return service;} }協議
dubbo
使用場景
適合大并發小數據量的服務調用,服務消費者遠大于服務提供者的情景
使用方式
dubbo:application:name: dubbo-providerregistry:address: zookeeper://192.168.111.101:2181 #注冊地址 使用zookeeperprotocol:name: dubbo # 使用dubbo協議port: -1Triple
基于 http2上的協議、完全兼容grpc、更加高效
<dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-rpc-triple</artifactId><version>${dubbo.version}</version> </dependency>yaml
dubbo:application:name: dubbo-provider #dubbo提供者名稱registry:address: zookeeper://192.168.111.101:2181 #注冊地址 使用zookeeperprotocol:name: tri #使用triple協議port: -1其他
配置中心
Nacos
dubbo:config-center:address: nacos://127.0.0.1:8848Zookeeper
dubbo:config-center:address: zookeeper://127.0.0.1:2181應用級服務發現
應用 升級到 Dubbo 3.0 后,服務端自動開啟接口級 + 應用級雙注冊功能,默認—>無需開發者修改任何配置
# 雙注冊 dubbo.application.register-mode=all # 僅 應用級注冊 dubbo.application.register-mode=instance # 僅 接口級注冊 dubbo.application.register-mode=interfaceyaml文件
dubbo:application:name: dubbo-provider # dubbo提供者名稱register-mode: instanceregistry:address: zookeeper://192.168.111.101:2181 #注冊地址 使用zookeeper protocol:name: dubbo #使用dubbo協議port: -1延遲暴露
所有服務都將在 Spring 初始化完成后進行暴露,如果你不需要延遲暴露服務,無需配置 delay
延遲 5 秒暴露服務
@DubboService(version = "v1.0", delay = 5000) public class ServiceImpl implements AsyncService {}問題
線程池資源枯竭
服務端的 線程資源耗盡了。 默認情況下,Dubbo 服務端的業務線程數是 200 個。如果多個并發請求量超過了 200,就會拒絕新的請求,拋出此錯誤
dubbo:provider:threads: 300可能的原因
排查和解決步驟
總結
- 上一篇: 大学实验中如何进行光纤熔接、涂覆与测试?
- 下一篇: GCP/临床试验基础知识集锦