dubbo的整体的架构设计
dubbo网络通讯机制原理
为什么系统要进行拆分
假设我们不进行拆分系统,一个系统的代码全部在一个服务中,少则7,8万行代码,多则几十万代码,当我们去维护的时候就非常麻烦,如正常迭代开发,我修改其中一小段代码,可能造成其他功能的bug,并且多个人进行开发,多个文件修改经常引起代码冲突,
因此如果我们把服务进行拆分,2-3三人维护一份小的服务,每个服务大概几万代码,当我们修改服务的功能的时候,只需要关注修改的服务的功能,不需要在进行整个系统的全面回归测试,减少风险
如何拆分系统
拆分系统是一个长期的计划,不是一开始就可以做到最完美,如把一个服务可以根据业务进行拆分,每个服务大概几万代码,每个团队,分为各个小组,每个小组维护一个业务相关的代码,同时,系统后期可能越来越复杂,因此还要继续拆分,这样拆分,每个小组各自维护自己的代码,互不影响,并且可以调高整个团队的开发效率,但是,这样也会引入一些问题,就是分布式系统带来的复杂技术挑战
系统拆分后,是否可以不用dubbo
当然可以,我们完全可以使用spring mvc 的http请求,自己做自己的负载均衡,服务注册,监控,但是这样做就有点愚蠢了,开源的dubbo是一个rpc框架,本地进行接口调用,dubbo会生产动态代理,跟远程机器进行网络请求,且支持服务的上线和下线感知,重试,不需要我们自己处理,岂不是更好
dubbo有那些通信协议
- dubbo协议
默认协议,使用长连接,NIO异步通信,适合小数量大并发的服务调用,不适合大数据,比如文件传输,传视频,默认是用Hessian二进制序列化
因为dubbo协议采用单一长连接,因此理论上1个服务提供者需要20服务消费者才能压满网卡
为什么要采用单一长连接呢,是因为通常提供者服务较少,而消费者较多,比如当提供者有6台提供者,却有百台消费者,每天有1.5亿次调用,如果不是用长连接,很容易压垮提供者,长连接减少了连接握手验证等,并使用异步IO。
- rmi协议 走java二进制协议,多个短连接,适合消费者和提供者数据差不多,适用于文件的传输,
- hessian协议
走hessian序列化协议,多个短连接,适用于提供者数量比消费者数量还多,使用与文件传输
- http协议 走http协议,多个短连接,适用于应用程序和浏览器JS使用的服务,
- webservice协议 走SOAP协议,可以和原生WebSercice服务互相操作
dubbo支持那些负载均衡
- random loadbalance 默认配置,随机调用实现负载均衡,也可以根据不同权重分配流量
- roundrobin loadbalance 轮询负载均衡,均匀的将流量打在各个机器上,如果机器的性能不一致,容易导致有些机器负载过高,因此可以设置权重调整,让配置低的机器承受较少的流量,减少权重的值
- leastative loadbalance 最少活跃,如果机器性能越差,那么请求就越少,越不活跃就会接收更少的请求
- consistanthash loadbalance 一致性hash算法,相同参数的请求可以发到同一天机器,当提供者宕机的时候,会基于虚拟节点分配剩余的流量,抖动不太大,
dubbo的容错机制
- failover cluster 失败自动切换,当请求到的机器单机了,经过重试之后,还是不行,就会切换到其他机器,默认配置
- failfast cluster 一次调用失败,就立即失效,常用于写操作
- failsafe cluser 出现异常时候,直接忽略,常用于一些不重要的接口
- failback cluster 失败后台自动记录请求,然后定时请求,常用于消息队列
- forking cluster 并行调用多个提供者,只要一个成功返回立即返回
- broadcacst cluster 逐个调用所有的提供者provider
dubbo的SPI机制
SPI机制,全名server provider interface,具体的含义就是当你有一个接口,他有三个实现类,在工程中如何选择哪个实现类呢,这就是spi,需要根据你的配置,或者默认配置,找到对应的实现类加载进来,然后使用这个实现类。
在我们的jdk中也有这样的功能,比如你的工程有个接口A,接口A在工程A是没有实现类的,然后系统如何选择一个实现类呢,
这个时候你就可以自己实现一个jar包,让你的工程依赖这个jar,而jar里面对应的目录META-INF/services/放上一个文件,文件里面配置你的实现类,如果key=com.jpsyzg.MyservicesImpl.当工程在运行的时候,就会扫描到META-INF/services。下配置的实现类,
一般spi机制应用在插件场景,比如我们jdbc只是一个接口,当我们要实现mysql,就会引入mysql-jdbc-connector.jar,引入其他数据也是一样,然后使用jar包的实现类
而dubbo也引入了spi思想,他自己实现了一套spi机制
如官网可以实现很多的spi机制,比如我们协议扩展。
下图是我们自己实现的jar
代码语言:javascript复制src
|-main
|-java
|-com
|-xxx
|-XxxProtocol.java (实现Protocol接口)
|-XxxExporter.java (实现Exporter接口)
|-XxxInvoker.java (实现Invoker接口)
|-resources
|-META-INF
|-dubbo
|-org.apache.dubbo.rpc.Protocol (纯文本文件,内容为:xxx=com.xxx.XxxProtocol)
对应的目录配置如下META-INF/dubbo/org.apache.dubbo.rpc.Protocol:
代码语言:javascript复制xxx=com.xxx.XxxProtocol
已知扩展的spi如下
代码语言:javascript复制org.apache.dubbo.rpc.protocol.injvm.InjvmProtocol
org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol
org.apache.dubbo.rpc.protocol.rmi.RmiProtocol
org.apache.dubbo.rpc.protocol.http.HttpProtocol
org.apache.dubbo.rpc.protocol.http.hessian.HessianProtocol
然后配置对应扩展配置
代码语言:javascript复制<!-- 声明协议,如果没有配置id,将以name为id -->
<dubbo:protocol id="xxx1" name="xxx" />
<!-- 引用协议,如果没有配置protocol属性,将在ApplicationContext中自动扫描protocol配置 -->
<dubbo:service protocol="xxx1" />
<!-- 引用协议缺省值,当<dubbo:service>没有配置prototol属性时,使用此配置 -->
<dubbo:provider protocol="xxx1" />
正如protocal接口,默认是走dubbo协议,当然我们也可以替换他的协议,使用自己的,如果想要动态替换默认的实现类,需要使用@Adaptive,这个注解是镇谷底protocal生成代理类,这个代理类就会有代理代码,代理代码就会动态根据我们的配置,获取对应的实现类。
dubbo服务治理,降级如何理解
- 服务治理
- 调用链路自动生成 一个大型分布式系统,都是有大量的服务组成,服务之间的调用如何调用,这些东西完全可以有dubbo对各个服务调用自动记录下来,生成各个服务之间的依赖关系和调用链路生成,做成一张图
- 服务访问压力以及时长统计 服务之间的调用次数以及访问延时,都可以使用dubbo进行统计,这个些统计分为两个级别,一个级别是接口粒度,就是每个服务的每个接口每天调用多少次,第二个级别就是一个完整的请求链路经过几十个服务之后,全链路请求延时分别是多少,这样就可以知道系统的压力在哪里
- 其他 服务分层,避免循环依赖,调用链路失败监控以及报警,服务鉴权,每个服务的可用性的监控
- 服务降级
- 比如当服务A调用服务B,这个时候服务B挂掉了,服务A会重试几次,还是不行,如果还是不行,就直接降级,dubbo降级,就是实现一个接口的备用逻辑,返回空或其他,而且我们不能一直重试,还可已配置超时时间,等到的时间还是不行,就会降级,
持续关注,下一篇Mybatis全面总结,如果对您有一丝丝帮助,麻烦点个关注,也欢迎转发,谢谢