首先我们知道Dubbo是一个RPC框架,因此解决的问题是服务治理,这个治理是解决服务注册和调用列表的维护治理,产生注册中心维护服务列表和更新,同时方便远程调用和本地调用是一样的,同时方便解耦,我猜这个是dubbo框架产生的初衷吧。而服务的调用和服务的引用是采用网络编程框架Netty,由于其基于NIO,因此其具有很高的性能。同时因为服务的调用和服务的引用,与IM通信或者我们看到的Http请求三次握手是类似的,采用的是应答模式。
下面我们来看一下服务的调用和服务流程,如图1所示:
图1 服务提供、引用与注册中心、监控
从这张图,可以看到服务端则会事先将自己的信息注册到注册中心,同时暴露接口,这样的话,方便服务提供者和服务引用调用,注册到注册中,以zookeeper为例,可以看到注册服务信息在树状列表中,也即dubbo下面的service下的providers的信息。也即它只负责将服务注册到注册中心,同时将服务提供信息统计到监控Monitor。
同时可以看到服务引用服务首先经过Proxy,而Proxy中会持有一个Invoker对象,然后出发invoke调用过程。在调用过程中,首先经过Cluster进行容错,比如默认的Failover,失败重试。经过Directory列表,这里包含动态注册列表信息和静态注册列表信息。如果用户配置了路由,则会进行用户配置的路由规则进行路由,常用的路由:脚本路由和条件路由。路由完之后,会进行负载均衡。常见的负载均衡:随机、轮询、最少活跃,千筛万选最终调用符合条件的Invoker。这里涉及到的容错、注册信息目录列表、路由、负载均衡,可以在图2中可以看到。
图2 Dubbo的Cluster、Router、Directory、LoadBalance
两条主线:订阅变更通知、进行数据传输。也即进行调用首先进行协议的适配Protocol,适配之后,进行服务的订阅subscribe和notify变更通知,如图1。接着进行Transporter操作,满足条件的Invoker会调用Client,采用同步的方式,默认采用Netty进行数据交互。这个过程会首先会对Header进行编码Codec,对Body进行序列化,然后调用服务端。服务端会进行收发Dispather到线程池中进行处理。此时它会根据请求找到Invoker,也即代理找到具体的接口,从而拿到实现,如图3。
图3 远程调用
也就是采用注册建立服务提供和服务引用的列表信息和变更,通过Netty进行远程调用,采用register将服务注册到注册中心,采用subscirbe从服务中心订阅需要调用的服务,采用notify进行变更通知操作,通知服务引用,服务提供者是否变更服务。而服务引用调用服务时,采用invoke适配协议拿到服务。同时可以看到Container,我猜它应该是启动的服务器,类似tomcat一样,这个待确认,这个从SPI中可以看到的默认服务器是Netty。服务的提供和调用采用Montior进行监控。