设计原则
Dubbo功能性需求
服务开发RMI或Hessian只能简单的暴露和引用远程服务,进行开发。通过配置服务的URL地址进行调用,F5等硬件进行负载均衡。
服务软负载均衡
通过服务注册中心,动态的注册发现服务,是服务的位置透明,实现软负载均衡和容错机制,降低对硬件负载均衡的依赖,减少部分成本。
服务依赖管理
服务间依赖关系错综复杂时,人工难以描述,需要自动画出应用间的依赖关系图。
服务监控
统计服务每天的调用量,响应时间,作为容量规划的参考指标。将某台机器的权重一直加大,并在加大的过程中记录响应时间的变化,直到响应时间到达阈值,记录此时的访问量,再以此访问量乘以机器数反推总容量。
服务治理
可在线动态调整权重、服务分钟隔离、禁启用服务。
如何做到优雅的开放扩展
微核心+插件式,平等对待第三方。(类似springIOC的功能)
由一个插件生命周期管理容器,构成微核心,核心不包括任何功能,这样可以确保所有功能都能被替换,并且,框架作者能做到的功能,扩展者也一定要能做到,以保证平等对待第三方,所有,框架自身的功能也要用插件的方式实现,不能有任何硬编码。
首先要统一扩展点的加载方式。
通常微核心都会采用Factory,IOC,OSGI等方式管理插件的生命周期。Dubbo采用Factory方式管理插件,曾经采用过JDK的SPI方式来实现Factory。所有Dubbo有个废弃的@Extension注解,最后被自己造了个SPI,也就是@SPI注解。
扩展的方式
扩充式与增量式、泛化式与组合式
扩充式:有的场景需要使用OSGI序列化,有的需要使用非OSGI序列化,基于原有的非OSGI序列化进行OSGI扩展,方便简单 ,只需要将流转化成byte[]进行处理。这样不管是不是需要OSGI场景,都会讲流进行byte[]转化,用不到OSGI序列化的场景都要为此付出代价。
增量式:非OSGI的代码原封不动,再加一个OSGI的实现,要用OSGI的时候,直接依赖OSGI实现即可。
泛化式,将扩展点逐渐抽象,去所有功能并集,新加功能总是能套入并扩充旧功能的概念。
组合式,将扩展点正交分解,取所有功能交集,新加功能总是基于旧功能之上实现。
路由器;容错机制;负载均衡器;发布者;订阅者
Dubbo核心功能,Invoker+Protocol+Exporter,这样可以分成协议层,路由分成组合,是一种非常好的扩展方式。
最大化复用,每个扩展点只封装一个变化因子
比如想扩展RPC协议,可能只想换一种通信传输,其他的复用。需要将协议拆解如下
全管道式设计
使用截面拦截而非模板方法
模板方法:一般开发为做到复用,将统一的公共逻辑抽出放到父类中,具体不同的动作则抽象出方法,由子类实现。如果统一公共部分的逻辑也非常复杂,这种方式就不适合了 。
截面拦截:将公共逻辑抽出,截面包装类似AOP的Wrapper类,通过拦截器实现,形成一条链(管道),每个功能都是调用链上的一环。
类似压栈的过程,将目标放到最后,前面就相当于截面private staticInvoker buildInvokerChain(final Invoker invoker, String key, String group) { final Invoker last = invoker; List filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group); if (!filters.isEmpty()) { for(int i = filters.size() - 1; i >= 0; --i) { final Filter filter = (Filter)filters.get(i); last = new Invoker () { public Class getInterface() { return invoker.getInterface(); } public URL getUrl() { return invoker.getUrl(); } public boolean isAvailable() { return invoker.isAvailable(); } public Result invoke(Invocation invocation) throws RpcException { return filter.invoke(last, invocation); } public void destroy() { invoker.destroy(); } public String toString() { return invoker.toString(); } }; } }复制代码
看下filter
最少概念,一致性概念模型
保持尽可能上的概念,助于理解,对于开放的系统尤为重要。另外,各接口都使用一致的概念,neng能相互指引,并减少模型转换。