Dubbo路由模块设计说明书.docx
《Dubbo路由模块设计说明书.docx》由会员分享,可在线阅读,更多相关《Dubbo路由模块设计说明书.docx(29页珍藏版)》请在冰豆网上搜索。
Dubbo路由模块设计说明书
Dubbo路由模块
设计说明书
修改记录
版本/状态
拟制人/
修改人
拟制/修改日期
更改理由
更改内容
(写要点即可)
V1.0
2015.12.21
新建
1.引言
1.1.微应用系统建设背景
近年来移动互联网发展迅速,每年移动互联网产生的流量增速达到60%,越来越多的业务及应用系统也开始推出支持各种移动终端的版本,而移动应用的增加反过来进一步促进了移动终端数量的快速增长。
公司根据移动互联网时代对业务的需求,提出了微应用商店,通过微应用商店提供更精细的业务功能。
随着互联网流量从桌面转向移动终端,以及物联网浪潮的兴起,提供适配多种终端的丰富、友好的用户体验对于应用系统提出了更高的要求。
传统的基于单一模型的应用系统,虽然在系统设计层面采用了分层架构设计,通常包括前端表现层、业务逻辑层、数据库访问层、应用集成层等,但最终系统打包成一个WAR或者EAR单一文件形式,该文件包含了所有的系统特性及功能,并通过集中部署的方式实现系统运行,通过部署在多台服务器上并结合负载均衡实现业务的高可用性,如图1单一架构应用系统所示。
图1单一架构应用系统
这种架构方式随着系统的演进,系统规模越来越庞大,子系统及模块之间的关系也越来越复杂,后续的开发及维护成本也不断提高,已经无法满足移动互联网应用对于系统的快速版本迭代及上线的需求,同时也严重影响了系统开发的效率。
针对单一架构应用系统暴露的问题,基于微服务架构的应用系统(以下简称微应用系统)应运而生。
微应用系统由一组规模较小的服务构成,每个服务以独立进程的方式单独运行,它们之间通过轻量级的进程间通信机制如RESTAPI进行通信,这些服务根据业务逻辑进行划分,每个服务有自己单独的数据库,通过自动化部署方式每个服务可以独立进行部署。
图2微应用系统架构
在微应用系统架构中,首先在业务服务层,每个业务服务以独立进程服务模式运行,实现特定的业务逻辑,并有独立的数据库实现数据存取,与其他业务服务之间通过良好定义的API接口进行交互。
业务聚合层负责对业务服务层的服务进行聚合,对服务调用返回的数据进行聚合及数据协议转换,对外提供更粗粒度的服务接口。
应用交付层负责对外提供系统应用层接口,对服务调用返回的结果根据用户终端进行优化,根据用户行为分析为用户提供定制化的展示方式。
1.2.微应用系统建设面临的挑战
微应用架构中应用内的各个服务可以独立、动态的进行伸缩,当服务进行伸缩时,其他调用方服务需要能够找到该服务的服务实例,并与之进行通信,使得请求能够分布到所有的服务实例中,从而实现该服务的水平可扩展性。
另外在服务调用过程中也需要通过负载均衡策略能够将针对该服务的请求均匀分布到所有的服务实例。
在大规模微应用系统服务化之前,应用可以通过RMI或者Hessian等工具,简单的暴露和引用远程服务,通过配置服务的URL地址进行调用,通过F5等硬件进行负载均衡。
但随着微应用系统中服务越来越多,系统面临着越来越多的挑战:
⏹当服务越来越多时,服务URL配置管理变得非常困难,F5硬件负载均衡器的单点压力也越来越大。
此时需要一个服务注册中心,动态的注册和发现服务,使服务的位置透明。
并通过在消费方获取服务提供方地址列表,实现软负载均衡和Failover,降低对F5硬件负载均衡器的依赖,也能减少部分成本。
⏹微应用中由于各个服务的独立性,任何服务的弹性伸缩、版本升级、系统故障等都可能导致该服务的状态发生变化甚至不可用,如何能够让服务使用者不受任何影响;
⏹微应用中每个服务都有自己独立的数据库,因为微应用拆分导致的原来在一个数据库的表被分散到了多个数据库,需要对服务屏蔽分布式数据库带来的复杂操作,为跨多个数据库的操作提供统一的数据访问方法;
⏹随着服务的调用量越来越大,服务的容量及性能问题就暴露出来,系统的扩容及运行优化需要性能监控及参数调整,所以需要监控服务的调用量、响应时间等,作为容量规划的参考指标。
其次,要可以动态调整权重,通过调整权重并在过程中记录响应时间的变化,直到响应时间到达阀值,记录此时的访问量,再以此访问量乘以机器数反推总容量。
所以服务的动态伸缩及调用请求需要统一的底层技术服务的支撑。
包括微应用及业务服务的注册与发现、微应用及业务服务请求的路由分发、微应用及业务服务的运行监控等,从而为微应用的运行提供运行支撑。
这其中微应用及业务服务的注册及发现是整个微应用的基础,微应用与业务服务请求的路由分发是核心,它是实现业务调用、负载均衡的关键。
微应用与业务服务的运行监控为微应用系统的运行提供保障。
2.微应用智能路由模块需求分析
为支撑微应用系统的改造及运行,公司在应用服务资源池的云应用管理系统提供的底层技术服务基础上,在微应用的分布式服务框架即智能路由(包含服务的注册发现)、微应用的使用(应用商店)、微应用的自动化部署(部署环境)、微应用的运行优化(监控统计)等几个方面开展了相应的产品研发工作。
这其中微应用的分布式服务框架即智能路由是实现服务之间调用及负载均衡的关键组件。
智能路由用于实现对应用请求的统一路由分发;提供服务智能路由机制来屏蔽因弹性伸缩、版本升级、系统故障等原因导致的服务的动态变化,让服务使用者不受任何影响;为由于微应用拆分导致的跨多个数据库的操作提供统一的数据访问方法。
图3微应用分布式框架智能路由
具体内容如图3微应用分布式框架智能路由所示,包括如下内容:
⏹应用路由:
为资源池中的所有微应用提供统一请求入口,由统一的路由分发到各个微应用;
⏹服务路由:
服务使用者从提供者地址列表中,基于负载均衡算法,选择一个提供者进行调用,如果调用失败就再选另一个调用;
⏹数据路由:
为跨多个数据库的操作提供统一的数据访问方法,屏蔽因为微应用拆分导致的原来在一个数据库的表被分散到了多个数据库中带来的复杂操作;
2.1.应用路由需求
应用路由要求为资源池中的所有微应用提供统一请求入口,由统一的路由分发到各个微应用,所以应用路由要求提供高可靠性及高可用性,以确保微应用的高可用性。
传统的硬件负载均衡设备如F5等可实现应用路由分发工作,但在微应用架构中其也存在明显的缺陷:
⏹集中式的负载均衡方案存在单点问题,由于所有服务调用流量都要经过负载均衡,所以当服务量和调用量大的时候,集中负载均衡容易成为瓶颈,而且一旦发生故障对整个系统的影响是灾难性的;
⏹基于硬件的集中式负载均衡方案其高可用依赖于硬件及网络配置,成本高且缺乏灵活性,不适宜弹性伸缩;
微应用架构下,资源池中的不同微应用在服务访问量及访问流量方面可能存在巨大差别,而且同一个微应用在不同时段负载变化也可能差异很大,所以要求负载均衡能够灵活的伸缩,能够通过集群的方式实现负载均衡本身的高可用性和可靠性,而且集群本身可动态伸缩。
2.2.服务路由需求
服务路由是指服务使用者在获取服务提供方列表后,从提供者地址列表中,基于负载均衡算法或者路由策略,选择一个提供者进行调用,如果调用失败就再选另一个调用。
具体需求如下:
2.2.1.服务负载均衡
当服务提供方有多个服务实例时,通过灵活的负载均衡策略选择一个实例进行服务调用:
⏹支持多种负载均衡策略,并且可自行扩展;
⏹支持随机负载均衡策略,并且可以按照权重设置随机概率;
⏹支持RoundRobin负载均衡策略;
⏹支持最少活跃调用数负载均衡策略,相同活跃数的采用随机策略;
⏹支持一致性Hash策略负载均衡,保证相同参数的请求总是发送到同一提供者,并且能够保证当某一个提供者不可用时,原本发往该提供者的请求,基于虚拟节点,平均调度到其他提供者;
2.2.2.集群扩展及容错
当服务提供方有多个服务实例时,可以将多个服务实例组织成一个集群,并对外伪装成一个服务实例,对调用方透明:
⏹支持多种集群容错方案,并支持自行扩展;
⏹支持Failover集群方案,调用失败时自动切换,重试其他服务实例,并且可以设置重试次数上限;
⏹支持Failfast集群方案,一旦调用失败,立即报错;
⏹支持Failsafe集群方案,失败安全,出现异常时,直接忽略;
⏹支持Failback集群方案,失败自动恢复,后台记录失败请求,定时重发;
⏹支持Forking集群方案,并行调用多个服务实例,只要一个成功即返回,可以设置最大并行数;
⏹支持Broadcast集群方案,广播调用所有提供者,逐个调用,任意一个服务实例报错则报错;
2.2.3.服务路由扩展及规则
当服务提供方有多个服务实例时,可以根据请求本身的信息(如参数、URL等)、服务调用方的信息(如IP地址等)、服务提供方的信息(如IP地址等)等进行路由过滤,最后过滤出一个或多个实例提供服务:
⏹可根据条件设置路由规则或者通过脚本定义路由规则;
⏹可以只针对特定服务或者特定服务实例IP地址设置路由规则;
⏹对于条件路由规则,支持条件表达式定义,条件表达式可以采用URL本身的字段及URL中的所有参数,并且支持匹配、不匹配等条件,另外支持多值、通配等方式;
⏹对于脚本路由规则,支持JDK引擎的所有脚本语言,如javascript、jruby、groovy等;
⏹当有多条路由规则时,可以设置优先级;
2.2.4.多协议支持
根据不同服务实现情况及不同服务调用方的实现方式,服务支持以不同协议来暴露服务:
●不同服务使用不同协议
●同一服务可以同时使用多种协议
2.2.5.多版本支持
当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。
例如在针对某个服务进行升级时,为不影响服务的可用性,可以选择在低压力时间段,先升级一半提供者为新版本,再将所有消费者升级为新版本,然后将剩下的一半提供者升级为新版本。
2.2.6.并发控制需求
⏹可以针对某个类的所有方法或者某个特定方法设置服务器端并发执行数量(或者占用线程池线程数)。
⏹可以针对某个类的所有方法或者某个特定方法设置每客户端并发执行数量(或者占用连接的请求数量)。
2.2.7.连接控制需求
⏹可以针对服务器端接受的连接数设置最大值;
⏹可以针对服务设置客户端使用的最大连接数(如果是长连接,表示该服务对每个提供者建立的长连接数)
2.2.8.令牌验证及权限扩展
在微应用中,针对不同调用方,调用前,需要通过用户鉴权,确定用户身份。
微应用中,对于服务方,需要按照调用方提供的鉴权信息,完成用户身份鉴定,并且通过系统中设置的用户权限,完成用户授权,确定用户是否具有调用该服务的权限。
⏹防止服务调用方不经过鉴权、授权直接访问服务提供方;
⏹统一进行鉴权控制,完成服务调用方身份确定;
⏹可以和已经存在的第三方鉴权系统对接;
⏹统一进行授权控制,完成服务调用者授权;
⏹可以和已经存在的第三方授权系统对接;
2.3.数据路由需求
微应用架构中每个服务由于可以独立开发、部署及升级,所以为避免不同服务之间的相互影响,每个服务都可以有自己独立的数据库。
不同服务对数据库的性能要求不同,所以要求数据库能够支持良好的伸缩性,以能够满足不同服务的性能要求,比如对于访问量较大的服务需要实现读写分离,但这种数据库层面的伸缩性及读写分离需要对应用层进行屏蔽。
数据路由要求能够实现数据库服务的可伸缩性,并且对服务透明。
另外采用数据路由后,对原有业务代码无侵入,不需要对代码进行修改。
3.微应用智能路由模块设计原则
⏹可靠性
Ø对于应用路由、服务路由及数据路由,都要提供高可用性解决方案,以确保微应用的可用性;
Ø对于应用路由,需要负载均衡通过集群模式实现应用请求分发的高可靠性;
Ø对于服务路由,即使服务注册与发现功能不可用后,服务提供方和服务调用方仍能通过本地缓存通讯;
Ø服务提供方无状态,任意一台宕掉后,不影响使用;
Ø服务提供方全部宕掉后,服务调用方应用将无法使用,并无限次重连等待服务提供方恢复;
Ø对于数据路由,某台后端数据库的异常不应影响后续的所有数据库读写访问,并且通过数据库同步技术能够尽快恢复发生异常的数据库;
⏹伸缩性
Ø对于应用路由、服务路由及数据路由,都要求能够根据负载情况进行动态伸缩;
Ø对于应用路由,软负载均衡要求能够动态增加或减少服务实例来适应负载的变化;
Ø对于服务路由,服务提供方无状态,可动态增加机器部署服务实例,并会推送新的服务提供方信息给服务调用方;
Ø对于数据路由,后端可以动态增加数据库,而对服务透明;
⏹可管理性
Ø必须保证对智能路由系统中的每个模块进行统一管理及监控,维护和管理的操作要简单方便,并且能够从中收集到统计信息为系统优化及参数调整提供依据。
4.微应用智能路由模块设计方案
4.1.应用架构设计
图4应用架构图
●软负载均衡:
负责客户端到微应用的路由处理,详细介绍见4.2.1章节。
●分布式服务框架:
负责微应用到聚合服务/业务服务的路由处理,以及聚合服务到业务服务的路由处理,详细介绍见4.2.2章节。
●分布式数据库框架:
负责业务服务到数据库的路由处理,详细介绍见4.2.3章节。
4.2.技术架构设计
4.2.1.软负载均衡设计
待补充。
4.2.2.分布式服务框架设计
4.2.2.1.分布式服务框架模型
图5分布式服务框架模型
⏹节点角色说明
•服务提供方:
暴露服务的服务提供方。
•服务调用方:
调用远程服务的服务调用方。
•注册中心:
服务注册与发现的注册中心。
•监控中心:
统计服务的调用次调和调用时间的监控中心。
•服务容器:
作为单独进程运行或者运行在servlet容器中,在服务容器开始运行时加载和运行所有服务提供方,供服务调用方调用服务,当服务容器停止后相关服务不再可用。
⏹调用关系说明
0.服务容器加载和运行服务提供方。
1.服务提供方在启动时,向注册中心注册自己提供的服务。
2.服务调用方在启动时,向注册中心订阅自己所需的服务。
3.注册中心返回服务提供方地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4.服务调用方,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5.服务调用方和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
4.2.2.2.注册中心
图6注册中心架构图
注册中心分为Web控制台和后端Zookeeper(集群)两部分。
1.Zookeeper后端
Zookeeper集群是注册中心的关键部分,负责接收服务提供方的服务注册、保存服务提供方信息,接收服务调用方的订阅并通知服务列表给服务调用方,其具体工作原理如下图所示:
图7注册中心Zookeeper功能设计
●基于Zookeeper的目录节点实现服务提供方的注册,将服务提供方信息保存在节点上
●基于Zookeeper目录节点上的监听和事件通知功能实现服务调用方对服务提供方的订阅和发布通知
●基于Zookeeper集群的主节点选举、数据同步功能实现注册中心的HA。
2.Web控制台
服务提供方查询需能通过调用Zookeeper的api获取到已经注册的所有服务提供方,以及订阅了该服务的服务调用方。
服务调用方查询需能通用通过Zookeeper的api获取已经订阅服务的所有服务调用方,以及其订阅的服务提供方。
服务通知模块需能够接收Zookeeper的服务提供方变更通知,结合服务调用方对服务提供方的订阅信息以及服务授权情况,将服务方信息发送给服务调用方。
服务授权模块需能接收用户在控制台前端页面配置并由控制台后端保存在Zookeeper节点中,同时提供授权情况的查询接口供服务通知模块引用。
4.2.2.3.服务提供方
图8服务提供方功能模块设计图
服务提供方由服务容器及运行在其上的各子模块组成,具体设计见以下各子章节。
4.2.2.3.1.服务容器
服务容器需能够以独立进程方式持续运行,服务容器启动后需完成以下初始化处理,以确保服务调用方可以调用服务提供方:
1.读取服务提供方的配置文件获取服务信息保存在缓存中
2.根据服务信息将服务注册到注册中心
3.根据服务的协议类型开放相应协议的访问接口
4.生成服务对应的代理服务对象
5.为代理服务对象添加附加服务链,服务链中的服务需要根据服务配置信息生成。
4.2.2.3.2.服务配置
以xml文件的方式配置所有的服务提供方及注册中心。
服务提供方配置项包含对应的spring-bean名字、注册中心、协议名称、最大并发数、最大连接数、令牌。
注册中心配置项包含zookeeper的ip和port,以及服务容器与zookeeper通信的port。
服务配置还需提供服务查询接口供服务容器初始化服务。
4.2.2.3.3.服务注册
服务被容器加载后需要注册到注册中心。
服务注册模块先读取服务配置获取Zookeeper的信息,再通过调用Zookeeper的api将服务名称、服务协议、令牌、版本号发送到Zookeeper上。
4.2.2.3.4.协议与传输
协议与传输模块负责建立服务方的通信服务端、等待调用方的连接和请求,并在处理完毕后响应调用方。
支持mina和netty协议
如果协议是mina,则通过mina框架创建通信服务端,调用方使用mina框架创建通信客户端,并相互通信。
如果协议是netty,则通过netty框架矿建通信服务端,调用方使用netty框架创建通信客户端,并相互通信。
4.2.2.3.5.代理服务
基于Spring技术在Spring容器中产生代理服务类,在代理原生服务的功能基础上还要完成令牌校验、访问统计、并发控制、连接控制等功能,各附加功能需要调用附加服务链完成。
4.2.2.3.6.附加服务链
每个代理服务都包含一个附加服务链,由一系列附加服务组成,附加服务包含令牌校验、访问统计、并发控制、连接控制。
代理服务类在处理服务请求时,先顺序执行附加服务链中的附加服务,然后再调用原生服务的处理逻辑。
若附加服务产生异常,则终止处理立即响应异常给调用方。
当请求处理完毕返回给调用方的时候,依然要经过附加服务链,仅处理访问统计和并发控制。
令牌校验:
从请求中获取服务令牌,与缓存中的服务令牌比较,若相同则校验通过继续处理,否则响应鉴权失败。
访问统计:
在本地缓存中保存各服务的访问统计数,当处理新的请求时根据服务名读取缓存中的统计数,并进行累加,同时记录请求到来时间,当请求处理完毕后还要经过访问统计,此时再用当前时间减去请求到来时间计算出本次请求处理时长,并保存在缓存中。
并发控制:
在本地缓存中保存各服务当前并发数,当处理新的请求时根据服务名读取当前并发数,计算并发数加1是否超过服务的最大并发数,如果超出则响应异常,否则继续执行下一个附加服务。
当请求响应阶段再次经过并发控制时,将对应并发数减1。
连接控制:
在本地缓存中保存各服务已建立的连接,当处理新的请求时根据服务名和客户端判断已建立连接数是否超过最大连接数,如果超出则响应异常、断开连接并删除缓存中的连接记录,否则继续执行下一个附加服务。
4.2.2.3.7.监控数据上报
监控数据上报需要每分钟触发一次,完成以下处理:
1.从缓存中读取所有服务的调用统计数及每次访问处理时长。
2.清空缓存中服务调用统计数和访问处理时长。
3.用访问处理总时长除以访问次数得出平均处理时长。
4.将调用统计书和平均处理时长发送给监控中心。
4.2.2.4.服务调用方
图9服务调用方功能模块设计图
服务调用方由上图中的各子模块组成,具体设计见以下各子章节。
4.2.2.4.1.服务调用方配置
以xml文件的方式配置所有的服务提供方及注册中心。
服务提供方配置项包含对应的spring-bean名字、注册中心、协议名称、最大并发数、最大连接数、令牌。
注册中心配置项包含zookeeper的ip和port,以及服务容器与zookeeper通信的port。
服务配置还需提供服务查询接口供服务容器初始化服务。
4.2.2.4.2.订阅与接收
图10服务订阅与接收
✧订阅
服务调用方启动时,在引用服务前首先将自身需要引用的服务注册到注册中心(zookeeper),然后订阅系统需要的服务。
如果同时引用多个接口,则上面的过程会重复执行多次。
✧接收
完成了服务订阅以后,服务调用方会与注册中心建立一个长连接,随后,会接收到注册中心主动发送的订阅信息。
注册中心主动推送订阅信息的的条件如下:
1.新的服务调用方注册
2.服务调用方订阅的服务发生变化(如:
新服务上线、下线等)
例如:
一个消费者注册了一个UserService,系统在启动时,首先声明自己是UserService的一个消费者,然后再向注册中心声明自己需要订阅UserService,最后,接收注册中心推送订阅的服务,缓存到本地。
如果服务提供方发生任何变化,也会接收到注册中心推送的更新信息。
4.2.2.4.3.监控数据上报
监控数据上报需要每分钟触发一次,完成以下处理:
1.从缓存中读取所有服务的调用统计数及每次访问处理时长。
2.清空缓存中服务调用统计数和访问处理时长。
3.用访问处理总时长除以访问次数得出平均处理时长。
4.将调用统计和平均处理时长发送给监控中心。
4.2.2.4.4.附加服务链
每个代理服务都包含一个附加服务链,由一系列附加控制组成,附加控制包含令牌校验、访问统计、并发控制、连接控制。
代理服务类在处理服务请求时,先顺序执行附加服务链中的附加服务,然后再调用原生服务的处理逻辑。
若附加服务产生异常,则终止处理立即响应异常给调用方。
当请求处理完毕返回给调用方的时候,依然要经过附加服务链,仅处理访问统计和并发控制。
令牌校验:
从本地获取服务令牌,附加在请求中一并上传。
访问统计:
在本地缓存中保存各服务的访问统计数,当处理新的请求时根据服务名读取缓存中的统计数,并进行累加,同时记录请求到来时间,当请求处理完毕后还要经过访问统计,此时再用当前时间减去请求到来时间计算出本次请求处理时长,并保存在缓存中。
并发控制:
在本地缓存中保存各服务当前并发数,当处理新的请求时根据服务名读取当前并发数,计算并发数加1是否超过服务的最大并发数,如果超出则响应异常,否则继续执行下一个附加服务。
当请求响应阶段再次经过并发控制时,将对应并发数减1。
连接控制:
在本地缓存中保存各服务已建立的连接,当处理新的请求时根据服务名和客户端判断已建立连接数是否超过最大连接数,如果超出则响应异常、断开连接并删除缓存中的连接记录,否则继续执行下一个附加服务。
4.2.2.4.5.容错集群
图10容错集群结构图
✧容错
容错的主要功能是在服务调用方实现的。
调用代理之后,是容错处理模块,它根据不同的容错模式,处理调用时产生的错误。
具体支持的容错模式包括:
✓FailoverCluster(缺省模式)
失败自动切换,当出现失败,重试其它服务器。
增加配置项设置重试次数。
✓FailfastCluster
快速失败,只发起一次调用,失败立即报错。
✓FailsafeCluster
失败安全,出现异常时,直接忽略。
✓FailbackCluster
失败自动恢复,后台记录失败请求,定时重发。
✧路由规则
●需要支持的路由规则包含:
按条件规则过滤服务,以条件表达式形式配置,路由时解析实际URL是否符合条件表达式。
条件表达式支持匹配、不匹配,匹配规则需支持多值和统配。
✧负载均衡
负载均衡的