1、促使dubbo产生原因

        大规模服务中,服务出现故障或者动态扩容,都需要消费者更新本地配置URL,成本代价太高。需要能够动态感知服务上下线以及服务地址的动态维护

        访问量过大,后端服务需要支持更多的访问量,需要扩容,而哪些服务需要扩容就显得格外重要,这就得进行服务监控,为扩容做参考指标,合理利用资源,提高资源利用率

         而dubbo不止解决以上两方面,同时还支持降级、流量控制、集群容错、负载均衡等

2、集群容错

        默认6种容错模式,还支持自行扩展,可插拔式的扩展

        Failover Cluster 失败自动转换。 适用读操作,事务操作会带来数据重复问题

        Failfast Cluster 快速失败。调用失败后,立即报错 。适用于一些幂等操作

        Failsafe Cluster 失败安全。出现异常,忽略异常

        Failback Cluster 失败后自动回复。服务调用异常,会记录以期定时重发。适合消息通知操作

        Forking Cluster 并行多个服务,只要一个成功就返回,

        Broadcast Cluster,广播调用所有的服务提供者,任意一个服务报错就表示服务调用失败,适合通知所有的服务提供者更新缓存或者本地资源信息。

        配置方式:@Service(cluster="failfast") 

        注:@service是dubbo的注解

实际使用中 查询用容错,增删改用快速失败

3、负载均衡

        在访问量大的情况下,通过水平扩容的方式增加多个节点来平衡请求流量,从而提升服务性能。具体如何平衡呢?这就需要用到对应的算法了。

        同样,dubbo提供4中均衡策略,默认策略是随机(random),同时也支持扩展,使用SPI机制(又是另外知识了,大家可以深入了解下)

        Random LoadBalance 随机算法。可以针对性能好的机器设置权重值,权重值越大,随机概率越大

        RoundRobin LoadBalance 轮询。

        LeastActive LoadBalance 最少活跃调用。处理较满的节点活得较少的请求

        ConsistentHash LoadBalance 一致性Hash。相同参数的请求总是发送到同一个服务提供者。

        配置方式:@Service(cluster = "failfast", loadbalance = "roundrobin")

3、服务降级

        服务器访问压力较大时,可以根据当前业务情况对不重要的服务进行降级,保证核心服务正常进行。

        降级分层:

                自动化:人工和自动

                功能:读服务和写服务

        故障降级:远程服务“挂了”,网络异常或者rpc服务返回异常,这种情况可以给客户端兜底数据;

        流量降级:每个微服务都有访问量的限制,超出限制就需要排队等待或者返回给客户端友好页面,提示”服务繁忙,请稍后再试“等信息。

        而dubbo提供一种叫mock的配置来实现服务降级 可以通过@Reference(mock="xxx")

        注:第一步:需要实现自动降级接口 第二步:在@Reference(mock="xxx")配置 其中xxx代表第一步的接口实现类

4、dubbo主机绑定规则

        查找环境变量:DUBBO_IP_TO_BIND属性配置的IP地址

        查找dubbo.protocol.host中配置的IP地址

        通过LocalHost.getHostAddress获取本机的IP地址

        如果配置了注册中心的地址,使用socket通信连接到注册中心的地址后,使用for循环通过socket.getLocalAddress().getHostAddress()扫描各个网卡获取网卡IP地址

        问题:主机绑定自上而下寻IP,但获取的IP地址有可能不是写入注册中心的地址,默认是从环境变量中获取。

        解决方案:

                在hosts文件中填写对应正确的IP地址映射

                在环境变量(DUBBO_IP_TO_BIND or DUBBO_IP_TO_REGISTRY)中填写正确的主机地址

                通过dubbo.protocol.host 设置主机地址

5、端口

        dubbo协议默认的端口号 20880

        webservice协议默认端口80

        在实际使用中,建议指定一个端口,避免端口产生冲突

   6、 Dubbo核心之SPI

        dubbo源码中,很多地方都用到了这三种代码。分别是自适应扩展点、指定名称的扩展点、激活扩展点

        ExtensLoader.getExtensionLoader(xxx.class).getAdaptiveExtension();

        ExtensLoader.getExtensionLoader(xxx.class).getExtension(name);

        ExtensLoader.getExtensionLoader(xxx.class).getActivateWxtension(url, key);

         SPI全称是Service Provider Interface,原本是JDK内置的一种服务提供发现机制,它主要用来做服务的扩展实现。SPI机制在很多场景中都有运用,比如数据库连接,JDK提供了java.sql.Driver接口,这个驱动类在JDK中并没有实现,而是由不同的数据库厂商来实现,比如Oracle、MySQL这些数据库驱动包都会实现这个接口,然后JDK利用SPI机制从classpath下找到相应的驱动来获得指定数据库的连接。这种插拔式的扩展加载方式,也同样遵循一定的协议约定。比如所有的扩展点必须要放在resources/META-INF/services目录下,SPI机制会默认扫描这个路径下的属性文件以完成加载。

Dubbo自定义协议扩展点         Dubbo或者SpringFactoriesLoader并没有使用 JDK内置的 SPI机制,只是利用了SPI的思想 根据实际情况做了一些优化和调整。Dubbo SPI的相关逻辑被封装在了 ExtensionLoader 类中,通 过 ExtensionLoader我们可以加载指定的实现类。         Dubbo 的 SPI扩展有两个规则:                 和JDK内置的 SPI一样,需要在resources 目录下创建任一目录结构:META-INF/dubbo、 META-INF/dubbo/internal、META-INF/services,在对应的目录下创建以接口全路径名命名 的文件,Dubbo 会去这三个目录下加载相应扩展点。                 文件内容和JDK内置的 SPI不一样,内容是一种Key 和 Value 形式的数据。Key是一个字 符串,Value 是一个对应扩展点的实现,这样的方式可以按照需要加载指定的实现类。

 Dubbo自适应扩展点               

        通过@Adaptive注解来申明: 作用在类上或者作用在方法上

 6、 Dubbo的IoC和AOP

        Ioc:系统运行过程中,动态得向某个对象提供它所需要的其他的对象,这种机制是通过依赖注入(Dependency Injection)来实现的

        在Dubbo的SPI机制中 injectExcepiton就是依赖注入的实现

        简单来说就是如果当前加载扩展类中存在一个成员对象,并且它提供了set方法,那么就会通过自适应扩展点进行加载并赋值。例如 org.apache.dubbo.registry.integration.RegistryProtocol

可以跟踪这个方法,参看源码

其中resource/dubbo/xxx下的是自定义的扩展点,需要用到dubbo的@SPI注解

        Aop:切面编程思想,主要是将业务逻辑与功能逻辑区分开来,然后在运行时或者类加载时进行织入。目的是降低代码耦合性,提供复用性

        dubbo的SPI机制中 ,以下代码片段就用到了AOP思想,基于Wrapper装饰器类实现对原有的

扩展类instance进行包装7、dubbo与spring的友好集成

@DubboComponentScan、@Service、@Reference

其中@DubboComponentScan注解中引入@Import({DubboComponentScanRegistrar.class})

DubboComponentScanRegistrar.class会扫描@Service、@Reference

而具体的源码大家有兴趣可以跟踪看看这两个类,有时间再给大家说说

如有不对之处,请大家多多指教

参考链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: