dubbo可以配置超时时间:
在controll中,远程调用服务注解@DubboReference(timeout = 1000)中可配置;
也可以在serviceimpl实现接口中,@DubboService(timeout=2000)中配置。
如果在controller层【消费方】和service实现层impl【生产方】中同时配置了超时时间,优先的是dubbo消费者
也就是说如果生产方和消费方同时配置了相同的配置,以消费方controller为准。
1、架构演进概述
随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。
单一应用架构
当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。
垂直应用架构
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,提升效率的方法之一是将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。
分布式服务架构
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。
流动计算架构
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。
2、Dubbo架构
下面我们看下dubbo架构
名词解释
节点 | 角色说明 |
---|---|
Provider | 暴露服务的服务提供方 |
Consumer | 调用远程服务的服务消费方 |
Registry | 服务注册与发现的注册中心 |
Monitor | 统计服务的调用次数和调用时间的监控中心 |
Container | 服务运行容器 |
调用关系说明【流程】
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心添加自己提供的服务。
- 服务消费方在启动时,向注册中心订阅自己所需的服务。
- 添加中心返回服务提供者地址列表给服务消费方,如果有变更,注册中心将基于长连接推送变更数据给服务消费方。
- 服务服务消费方,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 服务服务消费方和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
3、dubbo快速入门
上面我们介绍了dubbo的架构,下面我们来使用dubbo来进行开发,在开发之前,我们先看下面的图解:
从上图我们可用看出在一个标准的dubbo服务调用中,他分为3个部分
dubbo-interface:
负责接口的定义,这里我们通常定义***Face
结构的接口类,例如:UserFace
dubbo-producer:
【服务提供方】负责接口的实现,这里我们通常用==@DubboService==定义***FaceImpl
结构的接口类,例如:UserFaceImpl
dubbo-web:
【服务消费方】负责调用接口,通常我们在web层使用==@DubboReference==调用接口
下面我们来构建第一个dubbo服务,我们需要在dubbo-parent中pom.xml引入下列依赖:
<dependencies>
<!--接口定义层--> <dependency> <groupId>com.yyx.dubbo</groupId> <artifactId>dubbo-interface</artifactId> <version>${interFace.version}</version> </dependency> <!---spring-cloud-alibaba主配置--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!---springboot主配置--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring.boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies>
在dubbo-producer和dubbo-web中pom.xml导入:
<dependencies>
<!--接口定义层--> <dependency> <groupId>com.yyx.dubbo</groupId> <artifactId>dubbo-interface</artifactId> </dependency> <!--web支持--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--nacos支持--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--dubbo支持--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-dubbo</artifactId> </dependency> </dependencies>
3.1、定义接口
package com.yyx.dubbo;
/** * @Description: 定义接口 * @Version: V1.0 */ public interface UserFace { /** * 定义远程调用方法 * @return */ public String hello(String username); }
3.2、服务提供方实现
服务提供方:dubbo-producer负责服务的提供,我们需要把他添加到nacos添加中心中
(1)application.yml添加:
#服务配置
server: #端口 port: 8080 #服务编码 tomcat: uri-encoding: UTF-8 #spring相关配置 spring: #应用配置 application: #应用名称 name: dubbo-producer main: allow-bean-definition-overriding: true cloud: #nacos添加中心 nacos: discovery: server-addr: 192.168.200.129:8848 dubbo: #dubbo服务版本 application: version: 1.0.0 logger: slf4j #dubbo接口扫描路径 scan: base-packages: com.yyx.dubbo #dubbo服务添加 registry: address: spring-cloud://192.168.200.129 #dubbo服务协议类型及端口,线程数【这里是默认配置】 protocol: name: dubbo port: 28080 threads: 200 accesslog: logs/dubbo-producer-01.log
(2)实现dubbo-interface的Userface接口:
package com.yyx.dubbo.service;
import com.yyx.dubbo.UserFace; import org.apache.dubbo.config.annotation.DubboService; /** * @Description: * @Version: V1.0 */ @DubboService(version = "${dubbo.application.version}", timeout = 5000) public class UserFaceImpl implements UserFace { /** * 定义远程调用方法 * @param username * @return */ @Override public String hello(String username) { return "Hello SpringCloud Alibaba Dubbo " + username; } }
3.3、服务消费方实现
服务消费方:dubbo-web负责服务的接口消费,我们需要把他添加到nacos添加中心中
(1)application.yml配置文件:
#服务配置
server: #端口 port: 8081 #服务编码 tomcat: uri-encoding: UTF-8 #spring相关配置 spring: #应用配置 application: #应用名称 name: dubbo-web main: allow-bean-definition-overriding: true #nacos添加中心 cloud: nacos: discovery: server-addr: 192.168.200.129:8848 #dubbo消费端配置 dubbo: application: version: 1.0.0 logger: slf4j cloud: #表示要订阅服务的服务名,可以配置'*',代表订阅所有服务,不推荐使用。若需订阅多应用,使用 "," 分割。 subscribed-services: dubbo-producer scan: #扫描路径 base-packages: com.yyx.dubbo.web registry: address: spring-cloud://192.168.200.129 #dubbo服务协议类型及端口,线程数【这里是默认配置】 protocol: name: dubbo port: 28081 threads: 200 accesslog: logs/dubbo-web-01.log
(2)调用dubbo-interface的Userface接口:
package com.yyx.dubbo.web;
import com.yyx.dubbo.UserFace; import org.apache.dubbo.config.annotation.DubboReference; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @Description: * @Version: V1.0 */ @RestController @RequestMapping("user") public class UserController { @DubboReference(version = "${dubbo.application.version}", check = false) private UserFace userFace; @GetMapping("{userName}") public String helloUser(@PathVariable("userName") String userName){ return userFace.hello(userName); } }
3.4、测试
访问Nacos地址:http://192.168.200.129:8848/nacos/
可以点击 详情 查看服务注册的详细内容:
启动dubbo-producer和dubbo-web模块,访问:http://127.0.0.1:8081/user/yyx
4、业务模块开发流程初识
4.1、业务调用链路
在开始业务开发之前,我们首先看一下系统的调用链路,以 restkeeper-model-shop
模块为例,其调用的时序图如下所示:
以restkeeper-model-shop模块为例,一个标准的模块其模块结构如下
|——restkeeper-model-shop 商家服务平台
|———— model-shop-applet H5点餐小程序dubbo接口实现【服务提供方】 |———— model-shop-interface 商家平台所有dubbo接口定义 |———— model-shop-job-listen 商家服务平台定时任务及监听模块【监听消费、定义任务】 |———— model-shop-producer 后端业务dubbo接口实现【服务提供方】 |———— model-shop-service 核心业务层【被所有服务提供方、服务消费方、监听、定时任务依赖】 |———— model-shop-user 用户业务依赖于model-security-service的业务实现【服务提供方】 |———— model-shop-web 对外商家服务平台web层,被restkeeper-gateway-shop系统调用【服务消费方】
4.2、服务提供方分析
在restkeeper-model-shop模块中有3个【提供者】模块:
- model-shop-applet
- model-shop-producer
- model-shop-user
这里以model-shop-producer为例,首先查看模块依赖关系:
其中 model-shop-producer 模块他有以下职能:
- dubbo微服务【提供方】
- 【本地】调用service【核心业务层】实现dubbo服务接口的业务逻辑 - 对象转换:从POJO对象转换为VO对象
==注意:餐掌柜中为避免模块职能混乱,禁止服务提供方模块调用服务提供方模块,当产生跨服务接口调用,例如一个接口需要多个接口来支持,我们会放到web层进行服务调用然后业务组装,如果牵涉分布式事务问题,我们会采用seata方式来解决==
下面我们对model-shop-producer进行dubbo的集成,首先在model-shop-producer的pom.xml导入下列依赖:
<!-- Dubbo Spring Cloud Starter -->
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-dubbo</artifactId> </dependency>
再在model-shop-producer的application.yml添加定义如下:
dubbo:
#dubbo应用服务定义 application: #版本 version: 1.0.0 #日志 logger: slf4j scan: #扫描路径 base-packages: com.yyx.restkeeper registry: #添加中心:这里采用nacos添加中心 address: spring-cloud://192.168.200.129 #服务协议定义 protocol: #服务协议名称 name: dubbo #协议端口 port: 27077 #线程数 threads: 200 #dubbo调用日志 accesslog: logs/model-shop-producer-01.log
4.3、服务消费方分析
在restkeeper-model-shop模块中有1个【服务消费方】模块:model-shop-web,这里以model-shop-web为例,首先查看模块依赖关系:
其中model-shop-web模块他有以下职能:
- 传入参数的接收及校验工作
- 调用对应业务的dubbo服务,本身不负责业务逻辑的处理【服务消费方】 - 返回参数的封装,以及当下层发生异常,则抛出指定的自定义异常 - 定义swagger2的接口暴露,方便测试
下面我们对model-shop-web进行dubbo的集成,首先在model-shop-producer的pom.xml导入下列依赖:
<!-- Dubbo Spring Cloud Starter -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
再在model-shop-web的application.yml添加定义如下:
dubbo:
#dubbo应用服务定义 application: #版本 version: 1.0.0 #日志 logger: slf4j cloud: #表示要订阅服务的服务名,可以配置'*',代表订阅所有服务,不推荐使用。若需订阅多应用,使用 "," 分割。 subscribed-services: model-shop-producer,model-basic-producer,model-shop-applet,model-shop-user,model-trading-producer scan: #扫描路径 base-packages: com.yyx.restkeeper.web registry: #添加中心 address: spring-cloud://192.168.200.129 #服务协议定义 protocol: #服务协议名称 name: dubbo #协议端口 port: 27078 #线程数 threads: 200 #dubbo调用日志 accesslog: logs/model-shop-web-01.log
相比【服务提供方】来说【服务消费方】就多subscribed-services属性配置,此属性为订阅服务的服务名
4.4、服务接口定义
可能在以往的开发中我们只是知道三层架构【mapper、service、web】,那这里的face层是什么意思呢?大家都知道dubbo服务的调用逻辑,【服务消费方】调用【提供方】,那他们直接能调用的集成也就是声明统一的接口定义,在餐掌柜系统中dubbo层接口就起到此作用:
- 定义dubbo服务接口
- 被服务提供方依赖,按照face层的dubbo接口定义实现业务 - 被服务消费方依赖,从face层的dubbo中选择自己的业务接口
首先我们需要定义一个dubbo接口,那我们在哪里写能?从餐掌柜maven分层构建中我们可用发现,每个以restkeeper-model-***
开头的项目都是一个二级模块,并且模块中都有一个model-***-interface
的模块,例如:
没有错,这里就是我们定义face接口的三级模块,在定义dubbo接口的时,都需要找到类似:model-***-interface
的模块去书写
4.5、service核心业务
上面我们再介绍【dubbo层接口实现】提到dubbo层接口实现会调用核心业务,这个核心也就是这里的service层,还是以restkeeper-model-shop为例:
如果模块以model-***-service的格式出现,则表示此模块为核心模块,职能:
- pojo、mapper、service层定义
- 使用mybatis-push持久化框架完成CRUD操作 - 作为【核心业务层】被dubbo服务接口实现所调用 - 提供代码生成器的支持
商家平台启动依赖:
dubbo面试
注册中心宕机会不会影响远程调用?
如果是生产环境下(项目上线了),注册中心宕机了不影响服务之间的调用。
但是如果存在更新的服务或者新的服务,就不能够更新了。并且新的服务不能注册到注册中心。
如果是开发环境:
第一次调用,会影响服务的调用;
如果不是第一次调用,不会影响调用,因为消费者订阅了注册中心获取的数据后,会缓存到本地,
当在一次使用时,使用本地缓存信息发起远程调用。(数据缓存在dubbo文件夹下)。
另外如果服务的提供者全部宕机,服务消费者会无法使用,并无限次重连等待服务者恢复;
Dubbo 的负载均衡策略有哪些?
-
Random(随机):按权重随机分配(默认)。
-
RoundRobin(轮询):按权重轮询。
-
LeastActive(最少活跃调用):优先选择活跃数低的节点。
-
ConsistentHash(一致性哈希):相同参数的请求路由到同一节点。
Dubbo 的集群容错机制有哪些?
-
Failover(失败自动切换):默认策略,重试其他节点。
-
Failfast(快速失败):立即报错,用于非幂等操作。
-
Failsafe(失败安全):忽略异常,记录日志。
-
Failback(失败自动恢复):定时重试失败请求。
-
Forking(并行调用):同时调用多个节点,只要一个成功即返回。
-
Broadcast(广播调用):调用所有提供者,任意一个报错则报错。
Dubbo服务架构执行流程?
spring容器初始化服务的提供者、同时服务提供者向注册中心注册自己; 服务消费方启动通过订阅模式注册到注册中心,注册中心会将数据的变更异步主动推送到消费者方; 消费的服务方和提供服务段会同步。且两者都会异步通知给Monitor通知中心。
Dubbo调用方式?
主要这里要区别于eureka的拉取服务和nacos的订阅服务。
拉取是消费者从注册中心自己拉取服务(30),订阅服务是注册中心推送服务给消费方
spring container容器ioc,
启动容器,查询服务的提供方、将提供方服务注册到nacos注册中心中(初始化),
服务的消费方从注册中心【订阅服务】即注册中心会主动推送消息给消费者。
当获取到注册消息后,消费者同步到提供方。
# 注册中心推送服务是【【异步请求】】async
# 服务的消费方与服务的提供方是同步请求