1.多版本支持
注册多个版本,去实现不同方法
server端
<dubbo:service registry="master" interface="com.hw.dubbo.IHello"
ref="demoService1" protocol="dubbo" version="1.0.0"/>
<dubbo:service registry="master" interface="com.hw.dubbo.IHello"
ref="demoService2" protocol="dubbo" version="1.0.1"/>
<!--和本地bean一样实现服务-->
<bean id="demoService1" class="com.hw.dubbo.HelloImpl" />
<bean id="demoService2" class="com.hw.dubbo.HelloImpl2"/>
client端
会去调用server端demoService1的实现方法
<dubbo:reference id="demoService" interface="com.hw.dubbo.IHello" protocol="dubbo" version="1.0.0"/>
2.主机绑定
在发布一个Dubbo服务的时候,会生成一个dubbo://ip:port的协议地址,那么这个IP是根据什么生成的呢?大家可以在ServiceConfig.java代码中找到如下代码;可以发现,在生成绑定的主机的时候,会通过一层一层的判断,直到获取到合法的ip地址。
- 从配置文件中获取host
NetUtils.isInvalidLocalHost(host)
- 获取本地地址
host = InetAddress.getLocalHost().getHostAddress();
- 去本地路由找一个合适的ip
Socket socket = new Socket();
try {
SocketAddress addr = new InetSocketAddress(registryURL.getHost(), registryURL.getPort());
socket.connect(addr, 1000);
host = socket.getLocalAddress().getHostAddress();
break;
} finally {
try {
socket.close();
} catch (Throwable e) {}
}
3.集群容错
什么是容错机制?
容错机制指的是某种系统控制在一定范围内的一种允许或包容犯错情况的发生,举个简单例子,我们在电脑上运行一个程序,有时候会出现无响应的情况,然后系统会弹出一个提示框让我们选择,是立即结束还是继续等待,然后根据我们的选择执行对应的操作,这就是“容错”。
在分布式架构下,网络、硬件、应用都可能发生故障,由于各个服务之间可能存在依赖关系,如果一条链路中的其中一个节点出现故障,将会导致雪崩效应。为了减少某一个节点故障的影响范围,所以我们才需要去构建容错服务,来优雅的处理这种中断的响应结果
Dubbo提供了6种容错机制,分别如下
- failsafe 失败安全,可以认为是把错误吞掉(记录日志)
- failover(默认) 重试其他服务器; retries(2)
- failfast 快速失败, 失败以后立马报错
- failback 失败后自动恢复。
- forking forks. 设置并行数
- broadcast 广播,任意一台报错,则执行的方法报错
配置方式如下,通过cluster方式,配置指定的容错方案
4.服务降级
降级的目的是为了保证核心服务可用。
降级可以有几个层面的分类: 自动降级和人工降级; 按照功能可以分为:读服务降级和写服务降级;
- 对一些非核心服务进行人工降级,在大促之前通过降级开关关闭哪些推荐内容、评价等对主流程没有影响的功能
- 故障降级,比如调用的远程服务挂了,网络故障、或者RPC服务返回异常。 那么可以直接降级,降级的方案比如设置默认值、采用兜底数据(系统推荐的行为广告挂了,可以提前准备静态页面做返回)等等
- 限流降级,在秒杀这种流量比较集中并且流量特别大的情况下,因为突发访问量特别大可能会导致系统支撑不了。这个时候可以采用限流来限制访问量。当达到阀值时,后续的请求被降级,比如进入排队页面,比如跳转到错误页(活动太火爆,稍后重试等)
dubbo的降级方式: Mock
实现步骤
- 在client端创建一个TestMock类,实现对应IGpHello的接口(需要对哪个接口进行mock,就实现哪个),名称必须以Mock结尾
- 在client端的xml配置文件中,添加如下配置,增加一个mock属性指向创建的TestMock
- 模拟错误(设置timeout),模拟超时异常,运行测试代码即可访问到TestMock这个类。当服务端故障解除以后,调用过程将恢复正常
<!--声明需要暴露的服务接口 启动时不验证服务check="false" 版本号version="1.0.0" cluster="failsafe" timeout="50"-->
<dubbo:reference id="helloService"
interface="com.hw.dubbo.IHello"
protocol="dubbo"
registry="zookeeper"
mock="com.hw.dubbo.TestMock"
timeout="1"/>
当该接口报错时,走下面的mock方法,案例中把超时时间设置为1秒,来演示报错效果
public class TestMock implements IHello{
@Override
public String sayHello(String s) {
return "系统繁忙"+s;
}
}
2021-03-11 20:35:48,358 WARN [com.alibaba.dubbo.remoting.exchange.support.DefaultFuture] - [DUBBO] The timeout response finally returned at 2021-03-11 20:35:48.357, response Response [id=0, version=null, status=20, event=false, error=null, result=RpcResult [result=Hello1:李哲, exception=null]], channel: /192.168.137.1:51379 -> /192.168.137.1:20880, dubbo version: 2.5.4, current host: 192.168.137.1
系统繁忙gm
5.配置优先级别
以timeout为例,显示了配置的查找顺序,其它retries, loadbalance等类似。
- 方法级优先,接口级次之,全局配置再次之。
- 如果级别一样,则消费方优先,提供方次之。
其中,服务提供方配置,通过URL经由注册中心传递给消费方。
建议由服务提供方设置超时,因为一个方法需要执行多长时间,服务提供方更清楚,如果一个消费方同时引用多个服务,就不需要关心每个服务的超时设置。