dubbo特性
文章目錄
- 基本使用
- 參數(shù)校驗(yàn)
- pom
- 使用場(chǎng)景與實(shí)例
- 參數(shù)標(biāo)注示例
- 參數(shù)驗(yàn)證示例
- 開啟驗(yàn)證
- 多版本控制version
- 提供者
- 消費(fèi)者
- 負(fù)載均衡
- 服務(wù)分組
- 提供者
- 消費(fèi)者
- 服務(wù)超時(shí)
- 服務(wù)重試
- 集群容錯(cuò)
- 服務(wù)降級(jí)
- 異步調(diào)用
- 定義 CompletableFuture 簽名的接口
- 測(cè)試
- 啟動(dòng)時(shí)檢查
- 診斷與調(diào)優(yōu)
- 優(yōu)雅停機(jī)
- 調(diào)用結(jié)果緩存
- 注冊(cè)信息 簡(jiǎn)化
- 提供者
- 消費(fèi)者
- 注意
- 并發(fā)控制
- 連接控制
- 服務(wù)端連接控制
- 客戶端連接控制
- 粘滯連接
- 線程模型
- 配置注冊(cè)服務(wù)
- 協(xié)議
- dubbo
- Triple
- 其他
- 配置中心
- 應(yīng)用級(jí)服務(wù)發(fā)現(xiàn)
- 延遲暴露
- 問題
- 線程池資源枯竭
基本使用
參數(shù)校驗(yàn)
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>使用場(chǎng)景與實(shí)例
服務(wù)端在向外提供接口服務(wù)時(shí),解決各種接口參數(shù)校驗(yàn)問題
參數(shù)標(biāo)注示例
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) // 長(zhǎng)度或大小范圍private String name;@NotNull(groups = ValidationService.Save.class) // 保存時(shí)不允許為空,更新時(shí)允許為空 ,表示不更新該字段@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 // 必須為一個(gè)過去的時(shí)間private Date loginDate;@Future // 必須為一個(gè)未來的時(shí)間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;} }參數(shù)驗(yàn)證示例
import javax.validation.constraints.Min; import javax.validation.constraints.NotNull;public interface ValidationService {void save(@NotNull ValidationParameter parameter); // 驗(yàn)證參數(shù)不為空void delete(@Min(1) int id); // 直接對(duì)基本類型參數(shù)驗(yàn)證 }開啟驗(yàn)證
在客戶端驗(yàn)證參數(shù)
@DubboReference(methods = {},validation = "true") private GoodsService goodsService;在服務(wù)器端驗(yàn)證參數(shù)
@DubboService(validation = "true") public class GoodsServiceImpl implements GoodsService { }多版本控制version
提供者
@DubboService(version = "v1.0") public class GoodsServiceImpl implements GoodsService {}消費(fèi)者
@DubboReference(version = "v1.0") private GoodsService goodsService;負(fù)載均衡
注解配置
@DubboService(loadbalance = "roundrobin",methods = {}) public class GoodsServiceImpl implements GoodsService {}@DubboReference(loadbalance = "roundrobin",methods = {}) private GoodsService goodsService;服務(wù)分組
使用場(chǎng)景
當(dāng)一個(gè)接口有多種實(shí)現(xiàn)時(shí),可以用 group 區(qū)分
提供者
使用 @DubboService 注解,添加 group 參數(shù)
@DubboService(group = "demo") public class DemoServiceImpl implements DemoService {... }@DubboService(group = "demo2") public class Demo2ServiceImpl implements DemoService {... }消費(fèi)者
使用 @DubboReference 注解,添加 group 參數(shù)
@DubboReference(group = "demo") private DemoService demoService;@DubboReference(group = "demo2") private DemoService demoService2;// group值為 *----> 標(biāo)識(shí) 匹配任意服務(wù)分組 @DubboReference(group = "*") private DemoService demoService2;服務(wù)超時(shí)
超時(shí)后,進(jìn)行重試,也就是接下來的容錯(cuò)—> 設(shè)為 1 s
// 還可以進(jìn)行方法級(jí)別的 超時(shí)設(shè)置 // 誰(shuí)定義 服務(wù)就大概知道什么情況,建議 設(shè)置在服務(wù)提供方 @DubboService(version = "v1.0",timeout = 1000) public class GoodsServiceImpl implements GoodsService {}服務(wù)重試
- 設(shè)置超時(shí)時(shí)間,在這個(gè)時(shí)間段內(nèi),無法完成訪問,自動(dòng)斷開連接
- 如果出現(xiàn)網(wǎng)絡(luò)抖動(dòng),則這一次請(qǐng)求就會(huì)失敗
- Dubbo提供重試機(jī)制避免類似問題發(fā)生
- 通過retries 屬性設(shè)置重試次數(shù),默認(rèn)為 2次
集群容錯(cuò)
Failover Cluster
失敗自動(dòng)切換,當(dāng)出現(xiàn)失敗,重試其它服務(wù)器。通常用于讀操作,但重試會(huì)帶來更長(zhǎng)延遲。
可通過 retries="2" 來設(shè)置重試次數(shù)(不含第一次)。
重試次數(shù)配置如下:
@DubboReference(version = "v1.0",methods = {},cluster="failover") private GoodsService goodsService;服務(wù)降級(jí)
服務(wù)降級(jí)是—>指服務(wù)在非正常情況下進(jìn)行降級(jí)應(yīng)急處理,一般配合容錯(cuò)
使用場(chǎng)景
使用方式
@DubboReference(version = "v1.0", methods = {}, retries = 2, mock = "force:return null") private GoodsService goodsService;異步調(diào)用
定義 CompletableFuture 簽名的接口
服務(wù)接口定義
public interface AsyncService {CompletableFuture<String> sayHello(String name); }服務(wù)實(shí)現(xiàn)
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,與定義時(shí)相同!return "async response from provider.";});} }測(cè)試
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";}}訪問 秒相應(yīng)!!!
啟動(dòng)時(shí)檢查
Dubbo 缺省會(huì)在啟動(dòng)時(shí)檢查依賴的服務(wù)是否可用,** 不可用時(shí) 會(huì)拋出異常,阻止 Spring 初始化完成**
好處:以便上線時(shí),能及早發(fā)現(xiàn)問題,默認(rèn) check="true"
可以通過 check="false" 關(guān)閉檢查,比如,測(cè)試時(shí),有些服務(wù)不關(guān)心,或者出現(xiàn)了循環(huán)依賴,必須有一方先啟動(dòng)
// 推薦設(shè)置為false! @DubboReference(check = false) private GoodsService goodsService;check----->只用來 啟動(dòng)時(shí)檢查,運(yùn)行時(shí)沒有相應(yīng)的依賴仍然會(huì)報(bào)錯(cuò)!!!
診斷與調(diào)優(yōu)
優(yōu)雅停機(jī)
設(shè)置優(yōu)雅停機(jī)超時(shí)時(shí)間,缺省超時(shí)時(shí)間是 10 秒,如果超時(shí)則強(qiáng)制關(guān)閉。 該參數(shù)可在 dubbo.properties 文件里配置例如:配置為 30 秒
dubbo:application:name: dubbo-provider #dubbo提供者名稱shutwait: 30調(diào)用結(jié)果緩存
緩存類型
lru 基于最近最少使用原則刪除多余緩存,保持最熱的數(shù)據(jù)被緩存。
threadlocal 當(dāng)前線程緩存,比如一個(gè)頁(yè)面渲染,用到很多 portal,每個(gè) portal 都要去查用戶信息,通過線程緩存,可以減少這種多余訪問。
使用場(chǎng)景
結(jié)果緩存,用于加速熱門數(shù)據(jù)的訪問速度,Dubbo 提供聲明式緩存,以減少用戶加緩存的工作量
使用方式:可以指定方法或類進(jìn)行緩存
@DubboReference(cache = "lru",methods = {}) private GoodsService goodsService;注冊(cè)信息 簡(jiǎn)化
背景
服務(wù)為維度注冊(cè)進(jìn)入注冊(cè)中心,導(dǎo)致了數(shù)據(jù)量的膨脹,進(jìn)而引發(fā)注冊(cè)中心 (如 zookeeper) 的網(wǎng)絡(luò)開銷增大,性能降低
使用場(chǎng)景
數(shù)據(jù)量大導(dǎo)致注冊(cè)中心的網(wǎng)絡(luò)開銷增大,性能降低,減少注冊(cè)中心上服務(wù)的注冊(cè)數(shù)據(jù)
使用方式: 用 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 {// 暴露服務(wù)@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;}} }消費(fèi)者
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);} }注意
如果一個(gè)應(yīng)用中既有 provider 又有 consumer,那么配置需要合并成:
@Bean //注冊(cè)中心配置 public RegistryConfig registryConfig() {RegistryConfig registryConfig = new RegistryConfig();registryConfig.setAddress("zookeeper://127.0.0.1:2181");registryConfig.setSimplified(true);//只對(duì)provider生效registryConfig.setExtraKeys("retries,owner");return registryConfig; }并發(fā)控制
服務(wù)器端并發(fā)執(zhí)行(或占用線程池線程數(shù))不能超過 10 個(gè)
@DubboService(loadbalance = "roundrobin",executes = 10)客戶端并發(fā)執(zhí)行(或占用連接的請(qǐng)求數(shù))不能超過 10 個(gè)
@DubboReference(actives=10,methods = {}) private GoodsService goodsService;連接控制
Dubbo 中服務(wù)端和客戶端的連接控制
服務(wù)端連接控制
限制服務(wù)器端接受的連接不能超過 10 個(gè)
dubbo:application:name: dubbo-provider # 注冊(cè)的服務(wù)名registry:address: zookeeper://192.168.111.101:2181 # 注冊(cè)地址 使用zookeeperprotocol:name: dubbo # dubbo協(xié)議port: -1accepts: 10 # 連接控制客戶端連接控制
限制客戶端 服務(wù)使用連接不能超過 10 個(gè)
@DubboReference(connections = 10) private GoodsService goodsService;粘滯連接
使用場(chǎng)景
粘滯連接 用于 有狀態(tài)服務(wù),盡可能讓客戶端總是向同一提供者發(fā)起調(diào)用,除非該提供者掛了,再連另一臺(tái)
粘滯連接將自動(dòng)開啟 延遲連接,以減少長(zhǎng)連接數(shù)
使用方式:類或方法級(jí)別
@DubboReference(sticky = true, methods = {}) private GoodsService goodsService;線程模型
如何調(diào)整線程模型
在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各線程模型的配置值:
配置注冊(cè)服務(wù)
使用 Java Config 代替注解
注意: Java Config 是 DubboService 或 DubboReference 的替代方式,對(duì)于有復(fù)雜配置需求的服務(wù)建議使用這種方式
@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;} }協(xié)議
dubbo
使用場(chǎng)景
適合大并發(fā)小數(shù)據(jù)量的服務(wù)調(diào)用,服務(wù)消費(fèi)者遠(yuǎn)大于服務(wù)提供者的情景
使用方式
dubbo:application:name: dubbo-providerregistry:address: zookeeper://192.168.111.101:2181 #注冊(cè)地址 使用zookeeperprotocol:name: dubbo # 使用dubbo協(xié)議port: -1Triple
基于 http2上的協(xié)議、完全兼容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 #注冊(cè)地址 使用zookeeperprotocol:name: tri #使用triple協(xié)議port: -1其他
配置中心
Nacos
dubbo:config-center:address: nacos://127.0.0.1:8848Zookeeper
dubbo:config-center:address: zookeeper://127.0.0.1:2181應(yīng)用級(jí)服務(wù)發(fā)現(xiàn)
應(yīng)用 升級(jí)到 Dubbo 3.0 后,服務(wù)端自動(dòng)開啟接口級(jí) + 應(yīng)用級(jí)雙注冊(cè)功能,默認(rèn)—>無需開發(fā)者修改任何配置
# 雙注冊(cè) dubbo.application.register-mode=all # 僅 應(yīng)用級(jí)注冊(cè) dubbo.application.register-mode=instance # 僅 接口級(jí)注冊(cè) dubbo.application.register-mode=interfaceyaml文件
dubbo:application:name: dubbo-provider # dubbo提供者名稱register-mode: instanceregistry:address: zookeeper://192.168.111.101:2181 #注冊(cè)地址 使用zookeeper protocol:name: dubbo #使用dubbo協(xié)議port: -1延遲暴露
所有服務(wù)都將在 Spring 初始化完成后進(jìn)行暴露,如果你不需要延遲暴露服務(wù),無需配置 delay
延遲 5 秒暴露服務(wù)
@DubboService(version = "v1.0", delay = 5000) public class ServiceImpl implements AsyncService {}問題
線程池資源枯竭
服務(wù)端的 線程資源耗盡了。 默認(rèn)情況下,Dubbo 服務(wù)端的業(yè)務(wù)線程數(shù)是 200 個(gè)。如果多個(gè)并發(fā)請(qǐng)求量超過了 200,就會(huì)拒絕新的請(qǐng)求,拋出此錯(cuò)誤
dubbo:provider:threads: 300可能的原因
排查和解決步驟
總結(jié)
- 上一篇: 大学实验中如何进行光纤熔接、涂覆与测试?
- 下一篇: 什么样的知识付费系统功能,更有利于平台与