SpringCloud微服务集成Dubbo
1、Dubbo介绍
Apache Dubbo 是一款易用、高性能的 WEB 和 RPC 框架,同时为构建企业级微服务提供服务发现、流量治理、可观测、认证鉴权等能力、工具与最佳实践。用于解决微服务架构下的服务治理与通信问题,官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力, 利用 Dubbo 提供的丰富服务治理特性,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。Dubbo 被设计为高度可扩展,用户可以方便的实现流量拦截、选址的各种定制逻辑。
Dubbo官网: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 使用版本对应关系:https://github.com/alibaba/spring-cloud-alibaba/wiki/版本说明#2021x-分支 选择和项目相互对应的版本进行使用。这里我使用的是Dubbo 2.7.8
2、Dubbo连接注册中心
Dubbo推荐使用Zookeeper作为注册中心,Zookeeper是Apacahe Hadoop的子项目,是一个树型的目录服务,支持变更推送,适合作为 Dubbo 服务的注册中心,工业强度较高,可用于生产环境。除此之外Dubbo还可以使用阿里巴巴的nacos做注册中心。Nacos作为注册中心Dubbo使用与ZooKeeper基本相同,在使用上,不同的地方只有以下两点:
- 1、导入的依赖,配置不同;
- 2、注解不同,ZooKeeper使用@Service、@Reference注解,Nacos使用@DubboService、@DubboReference注解;
3、Dubbo负载均衡
- RandomLoadBalance:加权随机,默认算法,默认权重相同;
- RoundRobinLoadBalance:加权轮询,默认权重相同;
- LeastActiveLoadBalance:最少活跃优先+加权随机,能者多劳;
- ConsistentHashLoadBalance:一致性Hash,确定入参,确定提供者,适用于有状态的请求;
4、Dubbo Admin下载与使用
官网地址:https://github.com/apache/dubbo-admin
Dubbo和Dubbo Admin版本说明:https://cn.dubbo.apache.org/zh-cn/blog/2019/01/07/新版-dubbo-admin-介绍/
4.1、修改配置文件
进入dubbo-admin-server的resources目录,修改application.properties文件修改配置中心。默认为zookeeper:
admin.registry.address注册中心
admin.config-center 配置中心
admin.metadata-report.address元数据中心
由于我使用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 目录下执行命令启动前端:
npm run dev
这是官方项目开发环境说明,打开项目就能看到:
4.3 访问dubbo admin
浏览器输入地址进行访问,之前的dubbo-admin老版本用的是Tomcat启动的,后端端口是8080(可能会冲突),前端端口是8081
http://localhost:8081
新版的dubbo-admin用的是Netty,默认配置端口是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>
这里使用用户模块和订单模块模拟微服务使用Dubbo RPC的调用。在提供者模块中加入Dubbo依赖,在配置文件中设置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
配置添加成功后,在业务模块service层,新建一个对外提供的dubbo实现类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,"用户模块出现错误,需要回滚");
// }
// 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的对外接口服务模块用interface-module名称,在该模块中新建一个IUserExternalService接口,该接口实现在用户模块中的UserExternalServiceImpl实现类:
public interface IUserExternalService {
Response<List<UserExternal>> selectUserAll();
Response insert(UserExternal user);
}
现在我们的接口提供方已经编写完成了,接下来开始编写接口使用方也就是消费者。在订单模块中引入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的接口实现DubboUserServiceImpl类,意思是这个类是专门存放通过dubbo接口调用用户模块的业务类,后续在订单模块中处理用户模块信息都可以在该业务类中进行处理。
IDubboUserService类代码:
public interface IDubboUserService {
List<UserExternal> selectUserAll();
}
DubboUserServiceImpl业务类代码,需要在该类中使用@DubboReference(group = "userGroup",version = "2.0")注解注入IUserExternalService接口信息,通过Dubbo RPC实现远程调用,注意group 和version 需要和提供方相互对应,不然会注入失败:
@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);
//处理相关逻辑
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();
}
}
通过上面的代码,就可以实现服务模块与模块之间的远程调用了。使用Dubbo在订单模块调用用户模块就和调用其他业务类代码一样通过依赖注入就可以了,是不是非常方便。
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()", //当前方法的路径
blockHandler = "selectUserAll",
blockHandlerClass = CustomerBlockHandler.class, //触发限流 走该类的blockHandler = "selectUserAll"方法
fallback = "selectUserAllFallback",
fallbackClass = UserFallback.class, //dubbo调用接口异常,走该类的 fallback = "selectUserAllFallback"方法
exceptionsToIgnore = {IllegalArgumentException.class})
//fallback 负责业务异常 blockHandler限流方法 exceptionsToIgnore 报该异常fallback不处理
@GlobalTransactional(rollbackFor = Exception.class,timeoutMills = 30000,name = "order_tx_group") //seata事务注解,目前没有使用后面会在seata博客中介绍。
public List<UserExternal> selectUserAll() {
//添加blog
Blog blog = new Blog();
blog.setUid(UUID.randomUUID().toString());
blog.setTitle("dubbo事务测试Test");
blog.setContent("dubbo事务测试Test啊的服务器打");
blog.setSummary("12");
blog.setTagUid("3c16b9093e9b1bfddbdfcb599b23d835");
blogService.insert(blog);
//处理相关逻辑
Response<List<UserExternal>> response = userExternalService.selectUserAll();
// boolean flag = true;
// if (flag == true){
// throw new ParamException(500,"用户模块出现错误,需要回滚");
// }
UserExternal user = new UserExternal();
user.setUserName("dubbo事务");
user.setAccount("system");
user.setEmail("dubbo@gemail.com");
Response insert = userExternalService.insert(user);
System.out.println(insert);
return response.getModel();
}
}
CustomerBlockHandler处理限流的相关代码:
@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信息,调用接口被限流。。。。。");
return Response.fail(FallbackErrorEnum.REDIS_FIND_FALL);
}
public List<UserExternal> selectUserAll(BlockException exception){
log.error("添加订单|添加用户信息,触发限流控制。。。。。");
throw new ParamException(600,"添加用户信息异常:"+exception.getMessage());
}
}
UserFallback异常处理:
@Slf4j
public class UserFallback {
public static List<UserExternal> selectUserAllFallback(Throwable throwable) {
log.error("添加订单|添加用户信息异常,触发熔断兜底操作。");
throw new ParamException(600,"添加用户信息异常,触发兜底操作");
}
}
6、总结
SpringCloud集成Dubbo到目前为止就介绍完毕了,希望本博客对你有所帮助。目前只介绍了如何使用dubbo,dubbo还有需多需要去学习的地方,让我们持续学习新的知识,来应对工作中的各种问题。
SpringCloud微服务集成Dubbo的更多相关文章
- 微服务框架Dubbo与Springcloud的区别
微服务框架Dubbo与Springcloud的区别 微服务主要的优势如下: 1.降低复杂度 将原来偶合在一起的复杂业务拆分为单个服务,规避了原本复杂度无止境的积累.每一个微服务专注于单一功能,并通过定 ...
- Devops 开发运维高级篇之Jenkins+Docker+SpringCloud微服务持续集成(上)
Devops 开发运维高级篇之Jenkins+Docker+SpringCloud微服务持续集成(上) Jenkins+Docker+SpringCloud持续集成流程说明 大致流程说明: 1) 开发 ...
- Devops 开发运维高级篇之Jenkins+Docker+SpringCloud微服务持续集成——部署方案优化
Devops 开发运维高级篇之Jenkins+Docker+SpringCloud微服务持续集成--部署方案优化 之前我们做的方案部署都是只能选择一个微服务部署并只有一台生产服务器,每个微服务只有一个 ...
- 08 . Jenkins之SpringCloud微服务+Vue+Docker持续集成
简介 大致流程 /* 1.开发人员每天把代码提交到Gitlab代码仓库 2.jenkins从gitlab中拉取项目源码,编译并打包成war包,然后构建Docker镜像,将镜像上传到Harbor私有仓库 ...
- SpringCloud微服务学习笔记
SpringCloud微服务学习笔记 项目地址: https://github.com/taoweidong/Micro-service-learning 单体架构(Monolithic架构) Mon ...
- Java生鲜电商平台-SpringCloud微服务架构中核心要点和实现原理
Java生鲜电商平台-SpringCloud微服务架构中核心要点和实现原理 说明:Java生鲜电商平台中,我们将进一步理解微服务架构的核心要点和实现原理,为读者的实践提供微服务的设计模式,以期让微服务 ...
- SpringCloud微服务基础学习
看了蚂蚁课堂的微服务学习,确实学习了不少关于微服务的知识,现在总结学习如下 : SpringCloud微服务基础单点系统架构传统项目架构传统项目分为三层架构,将业务逻辑层.数据库访问层.控制层放入在一 ...
- SpringCloud微服务治理技术入门(SCN)
1.集群.分布式.微服务 首先先理解三个感念 什么是集群?: 同一个业务,部署在多个服务器上,目的是实现高可用,保证节点可用! 什么是分布式?: 一个业务分拆成多个子业务,部署在不同的服务器上,每个子 ...
- SpringCloud微服务框架复习笔记
SpringCloud微服务框架复习笔记 什么是微服务架构? 微服务是一种软件开发技术,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值.每个服务运行在其独立的进 ...
- 【微服务】之六:轻松搞定SpringCloud微服务-API网关zuul
通过前面几篇文章的介绍,我们可以轻松搭建起来微服务体系中比较重要的几个基础构建服务.那么,在本篇博文中,我们重点讲解一下,如何将所有微服务的API同意对外暴露,这个就设计API网关的概念. 本系列教程 ...
随机推荐
- React闭包陷阱
React闭包陷阱 React Hooks是React 16.8引入的一个新特性,其出现让React的函数组件也能够拥有状态和生命周期方法,其优势在于可以让我们在不编写类组件的情况下,更细粒度地复用状 ...
- Linux下Mysql的相关配置
Linux下Mysql的配置 安装 rmp -ivh MySQL-server-4.1.22-0.glibc23.i386.rpm --nodeps rmp -ivh MySQL-client-4. ...
- Python之猜数字游戏
说明: 本例改编自<Python编程快速上手>.例子很简单我就不多说了 直接上代码,给初学python练手用. 给你6次机会猜对一个预先生成好的1-20之间的整数.覆盖一下知识点: 条件语 ...
- java打印杨辉三角
package com.dylan.practice.interview; /** * 打印杨辉三角 * * 原理 * 1.每个数等于它上方两数之和 * 2.第n行的数字有n个 * * @author ...
- python课本学习-第五章
一.列表的概念 1.列表的创建 列表是由一组任意类型的值组合而成的序列,组成列表的值称为元素,每个元素之间用逗号隔开. 列表中的元素是可变的 #列表类似于c++中的数组,数组下标从0开始 list1 ...
- Golang Web 框架 Gin 基础学习教程集合目录
Gin Web 框架基础学习系列目录 01-quickstart 02-parameter 03-route 04-middleware 05-log 06-logrus 07-bind 08-val ...
- 第一百一十三篇: JS数组Array(二)数组方法 栈、队列、排序
好家伙, 在上一篇中,我们知道了, JS的数组中每个槽位可以存储任意类型的数据 那么,我们能通过数组去模仿某些数据结构吗? 答案是肯定的 1.栈方法 ECMAScript 给数组提供几个方法,让 ...
- python中json.dumps() 与json.dump(),json.load()与json.loads()区别?
json.dumps() 将 Python 对象转换为 JSON 字符串,并返回该字符串.而 json.dump() 将 Python 对象转换为 JSON 字符串,并将该字符串写入文件. json. ...
- forward配置
Adb connect 127.0.0.1:62001 adb forward tcp:27042 tcp:27042 #设置端口转发 adb forward tcp:27043 tcp:27 ...
- picgo+gitee+typora实现博客图床
背景 在微信公众号编写了推文后,从推文里面复制内容出来在其他平台发布,会出现图片展示不出来的情况,原因是因为该图片是微信的链接,被限制在其他平台显示. 诉求 编写的推文在多个平台都能进行发布,图片在多 ...