dubbo官网
官网地址:https://cn.dubbo.apache.org/zh-cn/overview/home/
上面是官网地址,想找什么东西可以进去看看
什么是dubbo?
Dubbo是Alibaba内部使用的一个分布式服务治理框架,可以和spring无缝衔接。
有服务远程调用、服务自动注册与发现、负载均衡、集群容错等功能特性。
好多好多…
为什么使用dubbo?
为什么会有dubbo,先从架构演化说起。
架构演化
单体架构
开始时用户量很小,代码都写在一个项目里,部署在一个服务器上。
缺点:
- 大家都维护一个项目,不能解耦,上线一起上,容易出问题。
- 一个机器流量有限,性能不行。
优点:大家都在一个项目上开发,用户服务调用订单服务,直接调用即可,不需要远程调用。
单体架构部署到多个服务器
随着用户量增加,用nginx做负载均衡,将请求分发到某个服务器上。多个服务器处理客户端的请求,压力会小很多。
本质上依然是单体项目,依然不需要远程调用。
但是有Nginx做负载均衡,nginx需要维护个服务列表,根据负载均衡策略将请求分发到某个服务器上。
单体项目拆分成多个微服务,每个微服务部署到多个服务器。
随着用户量增加,服务器压力越来越大,需要将单体项目拆分成多个微服务项目,并部署到多个服务器。
-
图片等学完了再补充
-
这时候用户服务调用订单服务,就需要远程调用。
-
每个微服务项目部署到多个服务器,需要负载均衡,将请求分发到某个服务器。
-
每个微服务项目部署到多个服务器,某个服务器挂掉了,或者某个服务器新加入,负载均衡需要感知。(服务动态注册与发现)
-
服务之间进行调用的时候,如果出现网络故障、或者服务故障导致
调用失败,需要集群容错
这个时候dubbo就能满足需求。
dubbo整体架构
上述节点说明如下:
- Provider 暴露服务的服务提供方
- Consumer 调用远程服务的服务消费方
- Registry 服务注册与发现的注册中心
- Monitor 统计服务的调用次数和调用时间的监控中心
- Container 服务运行容器
Springboot集成dubbo实例
参考:https://blog.csdn.net/ludkjava/article/details/134630024
dubbo部分特性的使用
这里的测试代码都是基于https://blog.csdn.net/ludkjava/article/details/134630024中的项目添加的代码。
服务注册与发现
注册中心的原理简介
- 首先B服务启动时会向注册中心注册自己的服务;
- 当A服务调用B服务的IAPIService接口时,A会从注册中心获取服务地址,并通过负-载均衡策略调用某个服务;
- 注册中心通过心跳感知B服务集群中的某个服务上下线,并更新注册中心中的服务列表;
- A服务不能每次都从注册中心获取服务列表,因此本地有缓存服务列表的机制;
- A服务的本地服务列表要及时更新,通过pull、push两种方式实现,pull是主动轮询注册中心,push是注册中心通过长连接主动推送;
dubbo注册中心
dubbo天然就支持服务注册与发现,官方建议使用zookeeper作为注册中心。
从dubbo2.7.x开始,支持的注册中心有很多
- Consul
- Etcd
- Nacos
- Sofa
- Zookeeper
- Eureka
- Redis
注册中心是个解决方案,根据上面组件的某些特性,来实现注册中心这一解决方案。
上面的组件并不是注册中心,是可以用来实现注册中心。
如分布式锁也是个解决方案,不是中间件。
多注册中心支持
dubbo支持同一服务向多个注册中心注册服务,或者不同服务分别注册到多个注册中心,可以同时引用注册在不同注册中心上的同名服务。
理论上没必要支持多种服务注册中心,都是历史原因导致的,随着项目的迭代、升级,总会出现各种场景、各种问题。
如图所示,公司在早期快速发展的时候,因为业务的野蛮增长导致对基础平
台缺少规划,技术团队也没什么精力去做这些治理,就有可能出现不同的系
统或者技术团队会选择不同的注册中心来治理自己的服务。这种情况下,就
会出现跨注册中心的服务通信。
多注册中心注册
一个服务注册在多个注册中心,如IAPIService服务同时注册在zookeeper、nacos注册中心上。
pom.xml
在原来的基础上,加上nacos的依赖
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
<version>${dubbo.version}</version>
</dependency>
application.properties
将原来的单注册中心,改为多注册中心
原来:
#注册中心
dubbo.registry.address=zookeeper://localhost:2181
现在:同时支持zookeeper和nacos
#多注册中心,zookeeper、nacos
dubbo.registries.zk-registry.id=zk-registry
dubbo.registries.zk-registry.address=zookeeper://localhost:2181
dubbo.registries.zk-registry.use-as-config-center=false
dubbo.registries.zk-registry.use-as-metadata-center=false
dubbo.registries.nacos-registry.id=nacos-registry
dubbo.registries.nacos-registry.address=nacos://localhost:8848
dubbo.registries.nacos-registry.username=nacos
dubbo.registries.nacos-registry.password=nacos
dubbo.registries.nacos-registry.use-as-config-center=false
dubbo.registries.nacos-registry.use-as-metadata-center=false
被注册的服务类ProviderServiceImpl
在@DubboService注解中加入属性registry = {“zk-registry”,“nacos-registry”},表示该服务同时注册在zookeeper、nacos中。其中"zk-registry、nacos-registry分别是上面application.properties文件中对应的id:
- dubbo.registries.zk-registry.id=zk-registry
- dubbo.registries.nacos-registry.id=nacos-registry
package com.ludk.dubboprovider.service;
import com.ludk.service.IAPIService;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Component;
/**
* @author ludengke
* @title: ProviderServiceImpl
* @projectName study
* @description: TODO
* @date 2023/11/2123:44
*/
@Component
@DubboService(interfaceClass = IAPIService.class,version = "2.6.0" ,timeout = 15000,registry = {"zk-registry","nacos-registry"})
public class ProviderServiceImpl implements IAPIService {
@Override
public String test(String from) {
return "from"+from;
}
}
消费端
消费端依然采用之前从zookeeper注册中心中获取服务,也可以参考服务端的形式。
测试
启动消费端,观察两个服务注册中心。可以发现IAPIService服务同时注册到两个注册中心上。
- zookeeper
- nacos
不同服务使用不同注册中心
不同服务使用不同的注册中心,也就是在同一个dubbo应用中,多个不同的
接口注册到不同的注册中心。
比如,在一个系统里面,如果存在多个站点,比如国际站点和中文站点,那
么一个某些服务为国际站点设计,有些服务为中文站点设计,那这个时候就
可以使用不同注册中心来进行隔离。
清空zookeeper、nacos下的节点
清空注册中心的数据,方便看效果
api模块添加接口IAPI2Service
package com.ludk.service;
/**
* @author ludengke
* @title: IAP2Service
* @projectName study
* @description: TODO
* @date 2023/12/314:03
*/
public interface IAPI2Service {
String test2(String param);
}
provider模块添加实现类ProviderService2Impl
通过registry = {“nacos-registry”}配置指定注册中心为nacos
package com.ludk.dubboprovider.service;
import com.ludk.service.IAPI2Service;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Component;
/**
* @author ludengke
* @title: ProviderService2Impl
* @projectName study
* @description: TODO
* @date 2023/12/314:05
*/
@Component
@DubboService(interfaceClass = IAPI2Service.class,version = "2.6.0" ,timeout = 15000,registry = {"nacos-registry"})
public class ProviderService2Impl implements IAPI2Service {
@Override
public String test2(String param) {
return param;
}
}
修改provider模块的ProviderServiceImpl
通过registry = {“zk-registry”}指定注册中心为zookeeper
package com.ludk.dubboprovider.service;
import com.ludk.service.IAPIService;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Component;
/**
* @author ludengke
* @title: ProviderServiceImpl
* @projectName study
* @description: TODO
* @date 2023/11/2123:44
*/
@Component
@DubboService(interfaceClass = IAPIService.class,version = "2.6.0" ,timeout = 15000,registry = {"zk-registry"})
public class ProviderServiceImpl implements IAPIService {
@Override
public String test(String from) {
return "from"+from;
}
}
测试
启动provider模块,查看两个注册中。
- IAPIService注册在zookeeper注册中心上
- IAPI2Service注册在nacos注册中心上
应用级服务注册与发现
Dubbo3以前,一直以来都是面向 RPC 方法去定义服务的,并且这也是 Dubbo 开发友好性、治理功能强的基础。
当然这种方式也带来了很多的不足,
- 注册中心上存储的数据更多了,增加了数据推送压力。
- 业内主流的微服务模型(Spring Cloud、Kubernetes Native Service),都是基于应用纬度的服务注册发现。如果Dubbo要拥抱云原生,就必然需要和这些模型对齐。
因此在Dubbo3开始,增加了应用级别的服务注册发现,默认情况下,服务端会自动开启接口级和应用级的双重注册,这也是为了兼容Dubbo2.x版本考虑。
但是如果生产者和消费者都升级到了Dubbo3,就建议开启应用级别的注册
以后关闭接口级的订阅。
可以通过下面这个配置来设置
# 双注册
dubbo.application.register-mode=all
# 仅应用级注册
dubbo.application.register-mode=instance
还可以通过注册中心地址上配置参数registry-type=service来显示指定该注
册中心为应用级服务发现的注册中心,带上此配置的注册中心将只进行应用
级服务发现
dubbo.registry.address="zookeeper://192.168.8.133:2181?registrytype=
service"
注意:服务端配置该注册中心为应用级服务发现的注册中心,服务端与消费端端下面两个配置需要为true。
- 具体原因后面再研究
dubbo.registries.zk-registry.use-as-config-center=true
dubbo.registries.zk-registry.use-as-metadata-center=true
服务接口的版本支持
可以通过version这个属性设置接口或者方法的版本。
当我们在进行功能迭代,可能存在新的功能对老版本不兼容的时候,就可以通过版本号来过度。如果不需要区分版本号,可以使用version=“*”。
上面的代码有用到:
@DubboService(interfaceClass = IAPIService.class,version = "2.6.0" ,timeout = 15000,registry = {"zk-registry"})
启动检查
在Dubbo服务中,难免会出现循环依赖的情况,如下图所示。
而Dubbo在启动的时候,会默认去检查依赖的服务状态,并且建立通信连接。就会导致服务无法启动的问题。
Dubbo里面提供了一个check参数,可以通过这个参数来关闭启动检查。
这个参数可以修饰在三个层面:
- @DubboReference ,直接关闭某个服务的启动检查
- dubbo.consumer.check=false,关闭消费端所有服务的启动检查
- dubbo.registry.check=false,关闭注册中心启动时检查
负载均衡
dubbo不想SpringCloud,需要引入ribbon、LoadBalancer组件来实现负载均衡,dubbo默认集成了负载均衡。
- Random LoadBalance:权重随机算法,根据权重值进行随机负载
- RoundRobin LoadBalance:加权轮询算法
- ConsistentHash LoadBalance:一致性hash算法
- LeastActive LoadBalance:最少活跃调用数算法
- shortestresponse LoadBalance:最短响应时间负载均衡算法
用法:
@DubboReference(version ="2.6.0" ,registry = {"zk-registry"},loadbalance = "roundrobin")
其他特性
其他特性可以参考官方文档:
- 集群容错
- 服务降级
- 接口异步调用
- 调用链路隐式传参
- 调用信息记录
- 多协议支持
- 序列化
- 请求参数校验