SpringCloud微服務(wù)集成Dubbo的詳細(xì)過程
1、Dubbo介紹
Apache Dubbo 是一款易用、高性能的 WEB 和 RPC 框架,同時為構(gòu)建企業(yè)級微服務(wù)提供服務(wù)發(fā)現(xiàn)、流量治理、可觀測、認(rèn)證鑒權(quán)等能力、工具與最佳實踐。用于解決微服務(wù)架構(gòu)下的服務(wù)治理與通信問題,官方提供了 Java、Golang 等多語言 SDK 實現(xiàn)。使用 Dubbo 開發(fā)的微服務(wù)原生具備相互之間的遠程地址發(fā)現(xiàn)與通信能力, 利用 Dubbo 提供的豐富服務(wù)治理特性,可以實現(xiàn)諸如服務(wù)發(fā)現(xiàn)、負(fù)載均衡、流量調(diào)度等服務(wù)治理訴求。Dubbo 被設(shè)計為高度可擴展,用戶可以方便的實現(xiàn)流量攔截、選址的各種定制邏輯。
Dubbo官網(wǎng):https://cn.dubbo.apache.org/zh-cn/
Dubbo文檔:https://cn.dubbo.apache.org/zh-cn/overview/quickstart/
Dubbo GitHub地址:https://github.com/apache/dubbo
Dubbo 使用版本對應(yīng)關(guān)系:https://github.com/alibaba/spring-cloud-alibaba/wiki/版本說明#2021x-分支 選擇和項目相互對應(yīng)的版本進行使用。這里我使用的是Dubbo 2.7.8

2、Dubbo連接注冊中心
Dubbo推薦使用Zookeeper作為注冊中心,Zookeeper是Apacahe Hadoop的子項目,是一個樹型的目錄服務(wù),支持變更推送,適合作為 Dubbo 服務(wù)的注冊中心,工業(yè)強度較高,可用于生產(chǎn)環(huán)境。除此之外Dubbo還可以使用阿里巴巴的nacos做注冊中心。Nacos作為注冊中心Dubbo使用與ZooKeeper基本相同,在使用上,不同的地方只有以下兩點:
- 1、導(dǎo)入的依賴,配置不同;
- 2、注解不同,ZooKeeper使用@Service、@Reference注解,Nacos使用@DubboService、@DubboReference注解;
3、Dubbo負(fù)載均衡
- RandomLoadBalance:加權(quán)隨機,默認(rèn)算法,默認(rèn)權(quán)重相同;
- RoundRobinLoadBalance:加權(quán)輪詢,默認(rèn)權(quán)重相同;
- LeastActiveLoadBalance:最少活躍優(yōu)先+加權(quán)隨機,能者多勞;
- ConsistentHashLoadBalance:一致性Hash,確定入?yún)?,確定提供者,適用于有狀態(tài)的請求;
4、Dubbo Admin下載與使用
官網(wǎng)地址:https://github.com/apache/dubbo-adminDubbo和Dubbo Admin版本說明:https://cn.dubbo.apache.org/zh-cn/blog/2019/01/07/新版-dubbo-admin-介紹/
4.1、修改配置文件
進入dubbo-admin-server的resources目錄,修改application.properties文件修改配置中心。默認(rèn)為zookeeper:
admin.registry.address注冊中心 admin.config-center 配置中心 admin.metadata-report.address元數(shù)據(jù)中心
由于我使用nacos,修改注冊中心為nacos。 nacos注冊中心有 GROUP 和 namespace:
admin.registry.address=nacos://127.0.0.1:8848?group=DEFAULT_GROUP&namespace=public&username=nacos&password=nacos admin.config-center=nacos://127.0.0.1:8848?group=dubbo&username=nacos&password=nacos admin.metadata-report.address=nacos://127.0.0.1:8848?group=dubbo&username=nacos&password=nacos //改為自己的注冊中心: admin.registry.address=nacos://localhost:8848?group=DEFAULT_GROUP&namespace=23857f22-27ac-4947-988a-1b88d4eeb807&username=nacos&password=nacos admin.config-center=nacos://localhost:8848?group=DEFAULT_GROUP&namespace=23857f22-27ac-4947-988a-1b88d4eeb807&username=nacos&password=nacos admin.metadata-report.address=nacos://localhost:8848?group=DEFAULT_GROUP&namespace=23857f22-27ac-4947-988a-1b88d4eeb807&username=nacos&password=nacos
4.2、Dubbo Admin項目打包
在項目根目錄進行打包,跳過測試:
mvn clean package -Dmaven.test.skip=true
進入dubbo-admin-0.6.0/dubbo-admin-distribution/target 進行啟動后端:
java -jar dubbo-admin-0.6.0.jar
dubbo-admin-ui 目錄下執(zhí)行命令啟動前端:
npm run dev
這是官方項目開發(fā)環(huán)境說明,打開項目就能看到:

4.3 訪問dubbo admin
瀏覽器輸入地址進行訪問,之前的dubbo-admin老版本用的是Tomcat啟動的,后端端口是8080(可能會沖突),前端端口是8081
http://localhost:8081
新版的dubbo-admin用的是Netty,默認(rèn)配置端口是38080,前端端口38082
http://localhost:38082 或 http://localhost:38080
用戶名密碼都是root
登錄成功:

5、SpringCloud集成Dubbo
在SpringBoot模塊中引入maven依賴:
<!-- Dubbo Spring Cloud Starter -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>這里使用用戶模塊和訂單模塊模擬微服務(wù)使用Dubbo RPC的調(diào)用。在提供者模塊中加入Dubbo依賴,在配置文件中設(shè)置dubbo連接注冊中心和配置中心:
dubbo:
application:
name: user-service-model-provider
protocol:
name: dubbo
port: -1
provider:
group: DEFAULT_GROUP
version: 2.0
#port: 20881
registry:
address: nacos://${nacos.address:127.0.0.1}:8848?username=nacos&password=nacos
#配置nacos自定義命名空間
parameters:
namespace: 23857f22-27ac-4947-988a-1b88d4eeb807
group: DEFAULT_GROUP
# registry:
# address: zookeeper://${zookeeper.address:127.0.0.1}:2181
metadata-report:
address: nacos://${nacos.address:127.0.0.1}:8848?username=nacos&password=nacos
#配置nacos自定義命名空間
parameters:
namespace: 23857f22-27ac-4947-988a-1b88d4eeb807配置添加成功后,在業(yè)務(wù)模塊service層,新建一個對外提供的dubbo實現(xiàn)類UserExternalServiceImpl,需要使用@DubboService注解,@Service注解盡量不要使用,可以使用@Componet代替。代碼如下:
//@Service
@Component
@DubboService(timeout = 1000 * 10,group = "userGroup",version = "2.0")
public class UserExternalServiceImpl implements IUserExternalService {
@Autowired
private IUserService userService;
@Override
public Response selectUserAll() {
// try {
// TimeUnit.MILLISECONDS.sleep(1000*5);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
return Response.success(userService.selectUserAll());
}
@Override
public Response insert(UserExternal userExternal) {
// boolean flag = true;
// if (flag == true){
// throw new ParamException(500,"用戶模塊出現(xiàn)錯誤,需要回滾");
// }
// try {
// TimeUnit.MILLISECONDS.sleep(20000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
User user=new User();
BeanUtils.copyProperties(userExternal,user);
boolean save = userService.save(user);
if (save){
return Response.success();
}else {
return Response.fail();
}
}
}然后還需要在新建一個專門存dubbo的對外接口服務(wù)模塊用interface-module名稱,在該模塊中新建一個IUserExternalService接口,該接口實現(xiàn)在用戶模塊中的UserExternalServiceImpl實現(xiàn)類:
public interface IUserExternalService {
Response<List<UserExternal>> selectUserAll();
Response insert(UserExternal user);
}現(xiàn)在我們的接口提供方已經(jīng)編寫完成了,接下來開始編寫接口使用方也就是消費者。在訂單模塊中引入dubbo依賴,在配置文件中將dubbo連接注冊中心和配置中心:
dubbo:
application:
name: order-service-model-consumer
consumer:
group: DEFAULT_GROUP
version: 2.0
protocol:
name: dubbo
port: -1
registry:
address: nacos://${nacos.address:127.0.0.1}:8848?username=nacos&password=nacos
#配置nacos自定義命名空間
parameters:
namespace: 23857f22-27ac-4947-988a-1b88d4eeb807
# registry:
# address: zookeeper://${zookeeper.address:127.0.0.1}:2181
cloud:
subscribed-services: user-service-model-provider
metadata-report:
address: nacos://${nacos.address:127.0.0.1}:8848?username=nacos&password=nacos
#配置nacos自定義命名空間
parameters:
namespace: 23857f22-27ac-4947-988a-1b88d4eeb807下面我們需要引入剛剛新建存dubbo接口模塊的依賴包,然后就可以使用該接口了。首先建一個IDubboUserService的接口實現(xiàn)DubboUserServiceImpl類,意思是這個類是專門存放通過dubbo接口調(diào)用用戶模塊的業(yè)務(wù)類,后續(xù)在訂單模塊中處理用戶模塊信息都可以在該業(yè)務(wù)類中進行處理。
IDubboUserService類代碼:
public interface IDubboUserService {
List<UserExternal> selectUserAll();
}DubboUserServiceImpl業(yè)務(wù)類代碼,需要在該類中使用@DubboReference(group = "userGroup",version = "2.0")注解注入IUserExternalService接口信息,通過Dubbo RPC實現(xiàn)遠程調(diào)用,注意group 和version 需要和提供方相互對應(yīng),不然會注入失敗:
@Service
@Slf4j
public class DubboUserServiceImpl implements IDubboUserService {
@DubboReference(group = "userGroup",version = "2.0")
private IUserExternalService userExternalService;
@Override
public List<UserExternal> selectUserAll() {
//添加blog
Blog blog = new Blog();
blog.setUid(UUID.randomUUID().toString());
blog.setTitle("dubbo測試Test");
blog.setContent("啊");
blog.setSummary("12");
blog.setTagUid("3c16b9093e9b1bfddbdfcb599b23d835");
blogService.insert(blog);
//處理相關(guān)邏輯
Response<List<UserExternal>> response = userExternalService.selectUserAll();
UserExternal user = new UserExternal();
user.setUserName("dubbo測試Test");
user.setAccount("system");
user.setEmail("dubbo@gemail.com");
Response insert = userExternalService.insert(user);
System.out.println(insert);
return response.getModel();
}
}通過上面的代碼,就可以實現(xiàn)服務(wù)模塊與模塊之間的遠程調(diào)用了。使用Dubbo在訂單模塊調(diào)用用戶模塊就和調(diào)用其他業(yè)務(wù)類代碼一樣通過依賴注入就可以了,是不是非常方便。
5、dubbo使用Sentinel進行限流和異常兜底
需要引入Maven依賴:
<!-- 在dubbo中使用 Sentinel 需要添加下面依賴 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-apache-dubbo-adapter</artifactId>
</dependency>由于限流和兜底是消費方要處理的事情,所以我們只需要在訂單模塊中引入上面依賴即可。在DubboUserServiceImpl中,通過@SentinelResource注解處理,代碼如下:
@Service
@Slf4j
public class DubboUserServiceImpl implements IDubboUserService {
@DubboReference(group = "userGroup",version = "2.0")
private IUserExternalService userExternalService;
@Autowired
private IBlogService blogService;
// @PostConstruct
// private void initFlowRules(){
// System.out.println("Sentinel initFlowRules start===");
// List<FlowRule> rules = new ArrayList<>();
// FlowRule rule = new FlowRule();
// rule.setResource(IDubboUserService.class.getName());
// rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// // Set limit QPS to 20.
// rule.setCount(20);
// rules.add(rule);
// FlowRuleManager.loadRules(rules);
// System.out.println("Sentinel initFlowRules end====");
// }
@Override
@SentinelResource(value = "com.itmy.user.service.IUserExternalService:selectUserAll()", //當(dāng)前方法的路徑
blockHandler = "selectUserAll",
blockHandlerClass = CustomerBlockHandler.class, //觸發(fā)限流 走該類的blockHandler = "selectUserAll"方法
fallback = "selectUserAllFallback",
fallbackClass = UserFallback.class, //dubbo調(diào)用接口異常,走該類的 fallback = "selectUserAllFallback"方法
exceptionsToIgnore = {IllegalArgumentException.class})
//fallback 負(fù)責(zé)業(yè)務(wù)異常 blockHandler限流方法 exceptionsToIgnore 報該異常fallback不處理
@GlobalTransactional(rollbackFor = Exception.class,timeoutMills = 30000,name = "order_tx_group") //seata事務(wù)注解,目前沒有使用后面會在seata博客中介紹。
public List<UserExternal> selectUserAll() {
//添加blog
Blog blog = new Blog();
blog.setUid(UUID.randomUUID().toString());
blog.setTitle("dubbo事務(wù)測試Test");
blog.setContent("dubbo事務(wù)測試Test啊的服務(wù)器打");
blog.setSummary("12");
blog.setTagUid("3c16b9093e9b1bfddbdfcb599b23d835");
blogService.insert(blog);
//處理相關(guān)邏輯
Response<List<UserExternal>> response = userExternalService.selectUserAll();
// boolean flag = true;
// if (flag == true){
// throw new ParamException(500,"用戶模塊出現(xiàn)錯誤,需要回滾");
// }
UserExternal user = new UserExternal();
user.setUserName("dubbo事務(wù)");
user.setAccount("system");
user.setEmail("dubbo@gemail.com");
Response insert = userExternalService.insert(user);
System.out.println(insert);
return response.getModel();
}
}CustomerBlockHandler處理限流的相關(guān)代碼:
@Slf4j
public class CustomerBlockHandler {
/**
* 查詢用戶熱點限流測試
* @param name
* @param email
* @param exception
* @return
*/
public static Response selectUserBlockException(@RequestParam(value = "name",required = false) String name,
@RequestParam(value = "email",required = false) String email,
BlockException exception){
log.error("CustomerBlockHandler|selectUserBlockException is fail");
return Response.fail(FallbackErrorEnum.USER_MODULE_FALL);
}
/**
* 查詢限流
* @return
*/
public static Response redisFindBlockException(BlockException exception){
log.error("添加訂單 redis|添加用戶 redis信息,調(diào)用接口被限流。。。。。");
return Response.fail(FallbackErrorEnum.REDIS_FIND_FALL);
}
public static List<UserExternal> selectUserAll(BlockException exception){
log.error("添加訂單|添加用戶信息,觸發(fā)限流控制。。。。。");
throw new ParamException(600,"添加用戶信息異常:"+exception.getMessage());
}
}UserFallback異常處理:
@Slf4j
public class UserFallback {
public static List<UserExternal> selectUserAllFallback(Throwable throwable) {
log.error("添加訂單|添加用戶信息異常,觸發(fā)熔斷兜底操作。");
throw new ParamException(600,"添加用戶信息異常,觸發(fā)兜底操作");
}
}6、總結(jié)
SpringCloud集成Dubbo到目前為止就介紹完畢了,希望本博客對你有所幫助。目前只介紹了如何使用dubbo,dubbo還有需多需要去學(xué)習(xí)的地方,讓我們持續(xù)學(xué)習(xí)新的知識,來應(yīng)對工作中的各種問題。
到此這篇關(guān)于SpringCloud微服務(wù)集成Dubbo的文章就介紹到這了,更多相關(guān)SpringCloud集成Dubbo內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Zxing實現(xiàn)二維碼生成器內(nèi)嵌圖片
二維碼在現(xiàn)實中的應(yīng)用已經(jīng)很廣泛了,本文介紹了使用Zxing實現(xiàn)二維碼生成器內(nèi)嵌圖片,有需要的可以了解一下。2016-10-10
JVM實戰(zhàn)系列之CPU100%和內(nèi)存100%排查
本文主要介紹了JVM實戰(zhàn)系列之CPU100%和內(nèi)存100%排查,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
Java文件字符輸入流FileReader讀取txt文件亂碼的解決
這篇文章主要介紹了Java文件字符輸入流FileReader讀取txt文件亂碼的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09
詳解JAVA中implement和extends的區(qū)別
這篇文章主要介紹了詳解JAVA中implement和extends的區(qū)別的相關(guān)資料,extends是繼承接口,implement是一個類實現(xiàn)一個接口的關(guān)鍵字,需要的朋友可以參考下2017-08-08
自定義注解實現(xiàn)Spring容器注入Bean方式(類似于mybatis的@MapperScans)
本文介紹了如何通過自定義注解@MyService和@MyServiceScans在SpringBoot項目中自動將指定包下的類注入Spring容器,詳細(xì)解釋了創(chuàng)建自定義注解、定義包掃描器ClassPathBeanDefinitionScanner的作用與實現(xiàn)2024-09-09

